C #: объединение словаря и списка - PullRequest
1 голос
/ 20 сентября 2010

У меня есть 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<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», чтобы результат не содержал повторяющихся ключей, а также повторяющихся значений.

Вот мой исходный код.

        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 ]

3 голосов
/ 20 сентября 2010

Вот один из способов, которым вы могли бы сделать это с помощью 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);
2 голосов
/ 20 сентября 2010

Цикл этот код проще, но не 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...