如何合并两个ListKeyValuePair>包括空格
本文关键字:string KeyValuePair 空格 包括 List 何合并 合并 两个 | 更新日期: 2023-09-27 18:18:21
我有两个List对象,我想合并为一个List<KeyValuePair>
。我知道Enumerable.Zip
,但如果第二个列表为空,则结果列表为空。如果第二个List为空,我希望生成的List包含空格。例如,如果列表1有{"apple", "orange", "cherry"}
,列表2有{"", "", ""}
或没有元素,那么我希望结果列表为:
1)"苹果"、"
2)"橙色"、"
3)"樱桃"、"
我能想到的唯一方法是在列表1 (KeyValuePair
中的"keys")上执行foreach循环,其中我用空白值添加每个Key,然后在列表2上执行foreach循环并覆盖每个值。虽然这些列表是独立的,但它们意味着彼此关联(因此我将它们合并在一起)。
您可以使用自己的Zip方法。它可能看起来像这样:
public static class EnumerableExt
{
public static IEnumerable<TOut> ZipAll<TIn1, TIn2, TOut>(
this IEnumerable<TIn1> sequence1,
IEnumerable<TIn2> sequence2,
Func<TIn1, TIn2, TOut> combiner)
{
sequence1 = sequence1 ?? Enumerable.Empty<TIn1>();
sequence2 = sequence2 ?? Enumerable.Empty<TIn2>();
var seq1Enum = sequence1.GetEnumerator();
var seq2Enum = sequence2.GetEnumerator();
for(;;)
{
var hasMore1 = seq1Enum.MoveNext();
var hasMore2 = seq2Enum.MoveNext();
if(hasMore1 || hasMore2)
{
yield return combiner(
hasMore1 ? seq1Enum.Current : default(TIn1),
hasMore2 ? seq2Enum.Current : default(TIn2));
}
else
{
break;
}
}
}
}
你可以这样使用:
var a=new []{"hello", "world"};
var b=new string[]{};
var result = a.ZipAll(b,
(aa, bb) =>
new KeyValuePair<string,string>(
aa ?? string.Empty,
bb ?? string.Empty));
这是ZipAll
, Enumerable.Zip
的一个版本,如果一个集合比另一个集合短,它将返回两种集合类型的默认值。
public static class EnumerableEx
{
public static IEnumerable<TReturn> ZipAll<T1, T2, TReturn>(
this IEnumerable<T1> first,
IEnumerable<T2> second,
Func<T1, T2, TReturn> f,
T1 seed1,
T2 seed2)
{
var iter1 = first.GetEnumerator();
var iter2 = second.GetEnumerator();
while(iter1.MoveNext())
{
if(iter2.MoveNext())
yield return f(iter1.Current, iter2.Current);
else
yield return f(iter1.Current, seed2);
}
while(iter2.MoveNext())
yield return f(seed1, iter2.Current);
}
public static IEnumerable<TReturn> ZipAll<T1, T2, TReturn>(
this IEnumerable<T1> first,
IEnumerable<T2> second,
Func<T1, T2, TReturn> f)
{
return first.ZipAll(second, f, default(T1), default(T2));
}
}
用法:
//create KeyValuePairs + fill shorter list with empty strings
var zip = a.ZipAll(b, (x,y) => new KeyValuePair<string, string>(x,y), "", "");
//create tuples + fill with nulls
var zip = a.ZipAll(b, Tuple.Create);
小提琴:https://dotnetfiddle.net/INhbdg
如果您担心list2
比list1
短,那么您需要将空字符串附加到list2
以获得跨越偶数长度列表的zip:
list1
.Zip(
list2.Concat(Enumerable.Repeat("", list1.Count-list2.Count)),
(x, y) => new KeyValuePair<string, string>(x, y)
.ToList();
您可以使用索引选择out并连接它们的索引。这将在它们的索引上左连接两个枚举,允许在没有找到的情况下传递默认值。这不仅仅适用于字符串。我添加了默认值,因为在您的示例中是字符串。String的默认值是null,所以现在你可以直接传入String. empty .
public static class ExtensionMethods
{
public static IEnumerable<KeyValuePair<TFirst, TSecond>> ZipJoin<TFirst, TSecond>(this IEnumerable<TFirst> first,
IEnumerable<TSecond> second)
{
return first.ZipJoin(second, default(TSecond));
}
public static IEnumerable<KeyValuePair<TFirst, TSecond>> ZipJoin<TFirst, TSecond>(this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
TSecond defaultValue)
{
return (from l1 in first.Select((item, index) => new KeyValuePair<int, TFirst>(index, item))
join l2 in second.Select((item, index) => new KeyValuePair<int, TSecond>(index, item)) on l1.Key
equals l2.Key into l2Group
from l3 in l2Group.DefaultIfEmpty(new KeyValuePair<int, TSecond>(0, defaultValue))
select new KeyValuePair<TFirst, TSecond>(l1.Value, l3.Value));
}
}