簡體   English   中英

如何合並兩個列表<dynamic> C# 中具有特定條件的對象?</dynamic>

[英]How to merge two List<dynamic> objects into one with specific condition in C#?

列出對象 1

[ { "empId":10001, "empName":"test1" }, { "empId":10002, "empName":"test2" } ]

列出對象 2

[ { "empId":10001, "emailAddress":"test1@mail.com" }, { "empId":10002, "emailAddress":"test2@mail.com" } ]


Trying to get the merge result which matches "empId" in both objects.

結果

[
   {
      "empId":10001,
      "empName":"test1",
      "emailAddress":"test1@mail.com"
   },
   {
      "empId":10002,
      "empName":"test2",
      "emailAddress":"test2@mail.com"
   }
]

我試過https://www.newtonsoft.com/json/help/html/MergeJson.htm 但無法執行匹配邏輯“empId”

這是一些將加入和合並的代碼,在這里工作

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;

using Newtonsoft.Json;
                    
public class Program
{
    public static void Main()
    {
        var list1 = new[]
            { 
                new { empId = 10001, empName = "test1" },
                new { empId = 10002, empName = "test2" }
            };
        
        var list2 = new[]
            {
                new { empId = 10001, emailAddress = "test1@mail.com" },
                new { empId = 10002, emailAddress = "test2@mail.com" }
            };
        
        var results1 = list1.MergeJoin(list2, e => e.empId);
        
        Console.WriteLine($"{nameof(results1)}:");
        Console.WriteLine(JsonConvert.SerializeObject(results1, Formatting.Indented));
        Console.WriteLine();
        
        IList<dynamic> dynamicList1 = new List<dynamic>
        { 
            new { empId = 10001, empName = "test1", utterance = "wibble" },
            new { empId = 10002, empName = "test2", expression = "bemused" }
        };
        
        IList<dynamic> dynamicList2 = new List<dynamic>
        {
            new { empId = 10001, emailAddress = "test1@mail.com", IQ = "moron" },
            new { empId = 10002, emailAddress = "test2@mail.com", smell = "cheesy" }
        };
        
        var results2 = dynamicList1.MergeJoin(dynamicList2, e => e.empId);
        
        Console.WriteLine($"{nameof(results2)}:");
        Console.WriteLine(JsonConvert.SerializeObject(results2, Formatting.Indented));
    }
}

public static class Extensions
{
    public static IEnumerable<dynamic> MergeJoin<TKey>(
        this IEnumerable<dynamic> outer,
        IEnumerable<dynamic> inner,
        Func<dynamic, TKey> keyAccessor)
    {
        return outer.Join(
            inner,
            keyAccessor,
            keyAccessor,
            Merge);
    }
    
    public static dynamic Merge(dynamic left, dynamic right)
    {
        IDictionary<string, object> dictionary1 = GetKeyValueMap(left);
        IDictionary<string, object> dictionary2 = GetKeyValueMap(right);

        var result = new ExpandoObject();

        var d = result as IDictionary<string, object>;
        foreach (var pair in dictionary1.Concat(dictionary2))
        {
            d[pair.Key] = pair.Value;
        }

        return result;
    }

    private static IDictionary<string, object> GetKeyValueMap(object values)
    {
        if (values == null)
        {
            return new Dictionary<string, object>();
        }

        var map = values as IDictionary<string, object>;
        if (map != null)
        {
            return map;
        }

        map = new Dictionary<string, object>();
        foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values))
        {
            map.Add(descriptor.Name, descriptor.GetValue(values));
        }

        return map;
    }
}

這應該是output,

results1:
[
  {
    "empId": 10001,
    "empName": "test1",
    "emailAddress": "test1@mail.com"
  },
  {
    "empId": 10002,
    "empName": "test2",
    "emailAddress": "test2@mail.com"
  }
]

results2:
[
  {
    "empId": 10001,
    "empName": "test1",
    "utterance": "wibble",
    "emailAddress": "test1@mail.com",
    "IQ": "moron"
  },
  {
    "empId": 10002,
    "empName": "test2",
    "expression": "bemused",
    "emailAddress": "test2@mail.com",
    "smell": "cheesy"
  }
]

您正在使用的Merge() function 並不是您唯一需要的。 您需要 LINQ 的Join()來“合並”兩個列表,然后使用Merge()來合並各個項目:

var xs = JArray
    .Parse(@"[
        {""empId"": 10001, ""empName"": ""test1""},
        {""empId"": 10002, ""empName"": ""test2""}
    ]")
    .Values<JObject>();

var ys = JArray
    .Parse(@"[
        {""empId"": 10001, ""emailAddress"": ""test1@mail.com""},
        {""empId"": 10002, ""emailAddress"": ""test2@mail.com""}
    ]")
    .Values<JObject>();

var merged = xs.Join(
    ys,
    x => x["empId"],
    y => y["empId"],
    (x, y) => { x.Merge(y); return x; });

請注意,您可能只需將dynamic類型轉換回JObject以便更容易處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM