合并字典与重复键生成子词典

时间:2017-01-26 12:03:08

标签: c# linq dictionary

我正在尝试合并包含n个嵌套字典的两个字典。合并的行为需要采用重复键并创建字典作为其值。例如,合并这两个词典:

Data_A: {
    Data_B: {
        Data_C: "C",
        Data_F: "F",
    }
}

我希望这次合并导致:

Dictionary<string, object>[] dictionaries = new Dictionary<string, object>[]
{
    (Dictionary<string, object>)dictX, 
    (Dictionary<string, object>)dictZ
};

var result = dictionaries.SelectMany(dict => dict)
                         .ToLookup(pair => pair.Key, pair => pair.Value)
                         .ToDictionary(group => group.Key, group => group.First());

似乎无法找到任何解决方案,不只是将“值”取为“F”或“C”而不是将下一个字典添加到“Data_B”的“Value”属性

这是我到目前为止所取得的第一个“价值”,而不是创造一个新的,但它不是很正确:

var series = [];
series[1] = {
  data: [1,2,3]
};
Highcharts.chart('container', {
    series: series
});

3 个答案:

答案 0 :(得分:2)

类似,并作为扩展方法。

#endif

用法:

# Turn on URL rewriting
RewriteEngine On

# Installation directory
RewriteBase /

RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteCond %{HTTP_HOST} ![0-9]$ [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [L,R=301]

# Protect hidden files from being viewed
<Files .*>
    Order Deny,Allow
    Deny From All
</Files>

# Protect application and system files from being viewed
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]

# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php/$0 [PT]

更新

使用这些扩展方法,您可以继续合并。

public static class DictionaryExtensions
{
    public static IDictionary<TKey, List<TValue>> Merge<TKey, TValue>(
        this IDictionary<TKey, TValue> me,
        IDictionary<TKey, TValue> other
    )
    {
        var keys = me.Concat(other)
            .GroupBy(x => x.Key)
            .ToDictionary(
                x => x.Key,
                x => x.Select(z => z.Value).ToList()
            );
        return keys;
    }
}

用法:

var dic1 = new Dictionary<string, string> { { "B", "C" }, { "A", "X" } };
var dic2 = new Dictionary<string, string> { { "B", "F" }, { "D", "D" } };
var dicm = dic1.Merge(dic2);

答案 1 :(得分:1)

而不是获取.First(),为什么不返回.ToList()?这将为您提供所有词典中的密钥及其所有相关值。

var x = new Dictionary<string, object>();
x.Add("B", "F");
x.Add("A", "D");
var y = new Dictionary<string, object>();
y.Add("B", "G");
Dictionary<string, object>[] dictionaries = new Dictionary<string, object>[]
{
        x,
        y
};

var result = dictionaries.SelectMany(dict => dict)
                     .ToLookup(pair => pair.Key, pair => pair.Value)
                     .ToDictionary(group => group.Key, group => group.ToList()); /* here */

返回(来自C#交互式shell,因此格式化有点奇怪):

 Dictionary<string, List<object>>(2) { 
        { "B", List<object>(2) { "F", "G" } }, 
        { "A", List<object>(1) { "D" } } 
    }

答案 2 :(得分:1)

你只需要一些老式的递归。这假设字典的结构是兼容的,并且不会尝试合并字典和字符串值。

    Dictionary<string, object> MergeDictionary(IEnumerable<Dictionary<string, object>> dicts)
    {
        var l = dicts.SelectMany(d => d).ToLookup(kv => kv.Key, kv => kv.Value);
        return l.ToDictionary(
            g => g.Key,
            g => g.Count() == 1
                ? g.First()
                : MergeDictionary(g.Cast<Dictionary<string, object>>()));
    }

要测试它,你可以运行它,它会返回你想要的结果。

    static void TestMergeDictionary()
    {
        var dbx = new Dictionary<string, object> { { "Data_C", "C" } };
        var dx = new Dictionary<string, object> { { "Data_B", dbx } };

        var dbz = new Dictionary<string, object> { { "Data_F", "F" } };
        var dz = new Dictionary<string, object> { { "Data_B", dbz } };

        var da = MergeDictionary(new[] { dx, dz });
    }