合并字典数组

时间:2014-02-26 13:50:36

标签: json

鉴于以下两个字典数组,我如何合并它们,以便生成的字典数组只包含那些 version 最大的字典?

data1 = [{'id': 1, 'name': 'Oneeee', 'version': 2},
         {'id': 2, 'name': 'Two', 'version': 1},
         {'id': 3, 'name': 'Three', 'version': 2},
         {'id': 4, 'name': 'Four', 'version': 1},
         {'id': 5, 'name': 'Five', 'version': 1}]

data2 = [{'id': 1, 'name': 'One', 'version': 1},
         {'id': 2, 'name': 'Two', 'version': 1},
         {'id': 3, 'name': 'Threeee', 'version': 3},
         {'id': 6, 'name': 'Six', 'version': 2}]

合并的结果应如下所示:

data3 = [{'id': 1, 'name': 'Oneeee', 'version': 2},
         {'id': 2, 'name': 'Two', 'version': 1},
         {'id': 3, 'name': 'Threeee', 'version': 3},
         {'id': 4, 'name': 'Four', 'version': 1},
         {'id': 5, 'name': 'Five', 'version': 1},
         {'id': 6, 'name': 'Six', 'version': 2}]

2 个答案:

答案 0 :(得分:1)

以下内容如何:

//define data1 and Data2
var data1 = new[]{
                   new {id = 1, name = "Oneeee", version = 2},
                   new {id = 2, name = "Two", version = 1},
                   new {id = 3, name = "Three", version = 2},
                   new {id = 4, name = "Four", version = 1},
                   new {id = 5, name ="Five", version = 1}
                 };

var data2 = new[] {
                   new {id = 1,  name = "One", version = 1},
                   new {id = 2, name = "Two", version = 1},
                   new {id = 3, name = "Threeee", version = 3},
                   new {id = 6, name = "Six", version = 2}
                 };
//create a dictionary to handle lookups     
var dict1 = data1.ToDictionary (k => k.id);
var dict2 = data2.ToDictionary (k => k.id);

// now query the data
var q = from k in dict1.Keys.Union(dict2.Keys)
        select
                dict1.ContainsKey(k) ? 
                  (
                    dict2.ContainsKey(k) ?
                    (
                      dict1[k].version > dict2[k].version ? dict1[k] : dict2[k]
                    ) :
                    dict1[k]
                  ) :
                  dict2[k];

// convert enumerable back to array
var result = q.ToArray();

如果data1和data2是表格,那么数据库友好的替代解决方案......

 var q  = (
            from d1 in data1
            join d2 in data2 on d1.id equals d2.id into data2j
            from d2j in data2j.DefaultIfEmpty()
            where d2j == null || d1.version >= d2j.version
            select d1
          ).Union(
            from d2 in data2
            join d1 in data1 on d2.id equals d1.id into data1j
            from d1j in data1j.DefaultIfEmpty()
           where d1j == null || d2.version > d1j.version
           select d2
          );

  var result = q.ToArray();

答案 1 :(得分:0)

假设你有一些类(这里使用JSON.NET属性):

public class Data
{
    [JsonProperty("id")]
    public int Id { get; set; }
    [JsonProperty("name")]
    public string Name { get; set; }
    [JsonProperty("version")]
    public int Version { get; set; }
}

您可以将JSON解析为此Data对象的数组:

var str1 = @"[{'id': 1, 'name': 'Oneeee', 'version': 2},
              {'id': 2, 'name': 'Two', 'version': 1},
              {'id': 3, 'name': 'Three', 'version': 2},
              {'id': 4, 'name': 'Four', 'version': 1},
              {'id': 5, 'name': 'Five', 'version': 1}]";

var str2 = @"[{'id': 1, 'name': 'One', 'version': 1},
              {'id': 2, 'name': 'Two', 'version': 1},
              {'id': 3, 'name': 'Threeee', 'version': 3},
              {'id': 6, 'name': 'Six', 'version': 2}]";

var data1 = JsonConvert.DeserializeObject<Data[]>(str1);
var data2 = JsonConvert.DeserializeObject<Data[]>(str2);

因此,您可以连接这两个数组,按ID分组数据项,并从具有最高版本的每个组项中进行选择:

var data3 = data1.Concat(data2)
                 .GroupBy(d => d.Id)
                 .Select(g => g.OrderByDescending(d => d.Version).First())
                 .ToArray(); // or ToDictionary(d => d.Id)

结果(序列化回JSON):

[
  { "id": 1, "name": "Oneeee", "version": 2 },
  { "id": 2, "name": "Two", "version": 1 },
  { "id": 3, "name": "Threeee", "version": 3 },
  { "id": 4, "name": "Four", "version": 1 },
  { "id": 5, "name": "Five", "version": 1 },
  { "id": 6, "name": "Six", "version": 2 }
]