C#:合并字典和列表

时间:2010-09-20 06:06:16

标签: c# list dictionary

我有List String喜欢

List<String> MyList=new List<String>{"A","B"};

Dictionary<String, Dictionary<String,String>> MyDict=new Dictionary<String,Dictionary<String,String>>(); 

包含

 Key      Value
          Key     Value

   "ONE"        "A_1"  "1"
                "A_2"  "2"
                "X_1"  "3"
                "X_2"  "4"
                "B_1"  "5"

    "TWO"       "Y_1"  "1"
                "B_9"  "2"
                "A_4"  "3"
                "B_2"   "6"
                "X_3" "7"

我需要将列表和Dictionary合并为一个新词典

 Dictionary<String,String> ResultDict = new Dictionary<String,String>()

结果字典包含

Key Value

"A_1"   "1"
"A_2"   "2"
"B_1"   "5"
"A_4"   "3"
"B_2"   "6"
"X_2"   "4"
"X_3"   "7"

合并规则

  1. 首先添加子字符串等于列表中任何项目的项目。
  2. 然后合并“MyDict”中的项目,以便结果不应包含重复的键以及重复的值。
  3. 这是我的源代码。

            Dictionary<String, String> ResultDict = new Dictionary<string, string>();
            List<String> TempList = new List<string>(MyDict.Keys);
            for (int i = 0; i < TempList.Count; i++)
            {
                ResultDict = ResultDict.Concat(MyDict[TempList[i]])
                                                  .Where(TEMP => MyList.Contains(TEMP.Key.Contains('_') == true ? TEMP.Key.Substring(0, TEMP.Key.LastIndexOf('_'))
                                                                                                                : TEMP.Key.Trim()))
                                                  .ToLookup(TEMP => TEMP.Key, TEMP => TEMP.Value)
                                                  .ToDictionary(TEMP => TEMP.Key, TEMP => TEMP.First())
                                                  .GroupBy(pair => pair.Value)
                                                  .Select(group => group.First())
                                                  .ToDictionary(pair => pair.Key, pair => pair.Value);            }
            for (int i = 0; i < TempList.Count; i++)
            {
                ResultDict = ResultDict.Concat(MyDict[TempList[i]])
                                                  .ToLookup(TEMP => TEMP.Key, TEMP => TEMP.Value)
                                                  .ToDictionary(TEMP => TEMP.Key, TEMP => TEMP.First())
                                                  .GroupBy(pair => pair.Value)
                                                  .Select(group => group.First())
                                                  .ToDictionary(pair => pair.Key, pair => pair.Value);
            }
    

    它工作正常,但我需要消除两个for循环或至少一个 (使用LINQ或LAMBDA表达式的任何方式)

2 个答案:

答案 0 :(得分:3)

根据要求,这是使用LINQ和lambdas的一种方法:

var keysFromList = new HashSet<string>(MyList);
var results =
    MyDict.Values
          .SelectMany(x => x)
          .OrderBy(x => {
                            int i = x.Key.LastIndexOf('_');
                            string k = (i < 0) ? x.Key.Trim() 
                                               : x.Key.Substring(0, i);
                            return keysFromList.Contains(k) ? 0 : 1;
                        })
          .Aggregate(new {
                             Results = new Dictionary<string, string>(),
                             Values = new HashSet<string>()
                         },
                     (a, x) => {
                                   if (!a.Results.ContainsKey(x.Key)
                                           && !a.Values.Contains(x.Value))
                                   {
                                       a.Results.Add(x.Key, x.Value);
                                       a.Values.Add(x.Value);
                                   }
                                   return a;
                               },
                     a => a.Results);

答案 1 :(得分:2)

循环方式这个代码更简单,但不是Linq:

public static Dictionary<string, string> Test()
{
    int initcount = _myDict.Sum(keyValuePair => keyValuePair.Value.Count);

    var usedValues = new Dictionary<string, string>(initcount); //reverse val/key
    var result = new Dictionary<string, string>(initcount);
    foreach (KeyValuePair<string, Dictionary<string, string>> internalDicts in _myDict)
    {
        foreach (KeyValuePair<string, string> valuePair in internalDicts.Value)
        {
            bool add = false;
            if (KeyInList(_myList, valuePair.Key))
            {
                string removeKey;
                if (usedValues.TryGetValue(valuePair.Value, out removeKey))
                {
                    if (KeyInList(_myList, removeKey)) continue;
                    result.Remove(removeKey);
                }
                usedValues.Remove(valuePair.Value);
                add = true;
            }
            if (!add && usedValues.ContainsKey(valuePair.Value)) continue;
            result[valuePair.Key] = valuePair.Value;
            usedValues[valuePair.Value] = valuePair.Key;
        }
    }
    return result;
}

private static bool KeyInList(List<string> myList, string subKey)
{
    string key = subKey.Substring(0, subKey.LastIndexOf('_'));
    return myList.Contains(key);
}