Может быть, это видео поможет, Brain Carns столкнулся с теми же проблемами и исправил это: https://www.youtube.com/watch?v=bROui4ID9_Q
или вы можете посмотреть at: Flutter: сборка не удалась с исключением
Here is a solution using the aggregate extension method:
string result = values.Aggregate("",
(keyString, pair) =>
keyString + "\n" + pair.Key + ":"
+ pair.Value.Aggregate("",
(str, val) => str + "\n\t" + val)
);
There is no LINQ syntax for the aggregate clause in C# (but apparently there is in Visual Basic for some predefined functions).
This solution might look somewhat complex, but the aggregate method is quite useful.
It works like this: If you have a List
you can combine all values into a single aggregate value.
That is in contrast to the Select
method, which doesn't modify the length of the list. Or the Where
method, which does shrink the list, but it still remains a list (instead of a single value).
For example, if you have a list {1, 2, 3, 4}
you can combine them into a single value like this:
int[] xs = {1, 2, 3, 4};
int sum = xs.Aggregate(0, (sumSoFar, x) => sumSoFar + x);
So you give two values to the Aggregate
method; a seed value and a 'combiner' function:
0
in this case). x
. Вкратце, как Aggregate
метод работает с List
. Он работает так же на KeyValuePair
, но только с разными типами.
Я не уверен, как бы вы сделали это в LINQ, но используя лямбды, вы могли бы сделать что-то вроде:
string foo = string.Join(Environment.NewLine,
values.Select(k => k.Key + Environment.NewLine +
string.Join(Environment.NewLine,
k.Value.Select(v => "\t" + v).ToArray())).ToArray());
Хотя это не очень хорошо читается.
Я бы сделал выбор значений, чтобы поместить вещи в начальный список по элементам (используя string.Join для значения), а затем вставьте его в строку (снова используя string.Join).
IEnumerable<string> items = values.Select(v =>
string.Format("{0}{1}{2}", v.Key, Environment.NewLine + "\t",
string.Join(Environment.NewLine + "\t", v.Value.ToArray()));
string itemList = string.Join(Environment.NewLine, items.ToArray());
В LINQ нет ничего, что могло бы вам здесь помочь, потому что у вас есть отдельный набор требований для значения, чем вы делаете ключи (вы вкладываете между значениями).
Даже если это не так, в лучшем случае, LINQ поможет вам просто получить один источник перечисления для циклического переключения, который вы бы сделали в любом случае необходимо иметь какую-то логику разделения, чтобы указывать, когда вы обрабатываете набор значений по сравнению с ключом.
Суть в том, что у уже имеющегося словаря есть естественная группировка, которой LINQ не будет может помочь больше, если только вы не имеете дело с какой-либо операцией, кроме группировки (сортировка, проекция, фильтрация).
Если бы у вас был такой метод:
public IEnumerable<string> GetStrings
(KeyValuePair<string, List<string>> kvp)
{
List<string> result = new List<string>();
result.Add(kvp.Key);
result.AddRange(kvp.Value.Select(s => "\t" + s));
return result;
}
Тогда вы могли бы сделать это:
List<string> result = theDictionary
.SelectMany(kvp => GetStrings(kvp)).ToList();
Или в общем случае:
public static IEnumerable<T> GetFlattened<T, U>
( this KeyValuePair<T, List<U>> kvp,
Func<U, T> ValueTransform
)
{
List<T> result = new List<T>();
result.Add(kvp.Key);
result.AddRange(kvp.Value.Select(v => ValueTransform(v)));
return result;
}
List<string> result = theDictionary
.SelectMany(kvp => kvp.GetFlattened(v => "\t" + v))
.ToList();