在 linq 中,是否可以组合许多列表(相同类型),例如两个列表,
列表 1 = {a,b,c} 和列表 2 = {x,y,z}
变成 {[1,a] , [1,b] , [1,c] , [2,x] , [2,y] , [2,z] }
其中 [] 表示包含“列表标识符”的对
问题在于拥有任意牌组,其中每个牌组都是列表集合中的一个列表。
我正在尝试创建一个查询,以便我只能选择某个牌组中的牌,或者类似于 2 个或更多牌组的牌。
这可能是一个重复的问题,但我不知道如何进一步搜索这个问题。
List<List<int>> lists;
var combined = lists.Select((l, idx) => new { List = l, Idx = idx })
.SelectMany(p => p.List.Select(i => Tuple.Create(p.Idx + 1, i)));
var list1 = new List<string>() {a,b,c};
var list2 = new List<string>() {x,y,z};
var combined = list1.Select(x => new { id = 1, v = x }).Concat(list2.Select(x => new { id = 2, v = x }));
通常我会建议Enumerable.Zip用于组合多个列表,但是您似乎实际上希望将多个列表与列表计数器连接起来。
public IEnumerable<Tuple<int,T>> Combine<T>(params IEnumerable<T>[] lists) {
return lists.Select((x,i) => x.Select(y => Tuple.Create(i+1,y))).SelectMany (l =>l);
}
UPDATE 完全错过了 SelectMany 有 index 选项,所以上面的代码可以写成
public IEnumerable<Tuple<int,T>> Combine<T>(params IEnumerable<T>[] lists) {
return lists.SelectMany((x,i) => x.Select(y => Tuple.Create(i+1,y)));
}
然后你可以做
var list1 = new List<string> { "a", "b", "c" };
var list2 = new List<string> { "x", "y", "z" };
var combined = Combine(list1,list2);
组合将是可枚举的元组,Item1
是列表索引标识符(从 1 开始)和Item2
值。
此方法将处理多个列表,因此您可以轻松调用它:
var list3 = new List<string> { "f", "g" };
var combined = Combine(list1,list2,list3);
尝试使用Concat
new[] {'a','b','c'}
.Select(v=>new Tuple<int,char>(1, v))
.Concat(
new[] {'x','y','z'}.Select(v=>new Tuple<int,char>(2, v))
)
您可以合并列表,例如:
var first = new List<string> {"a","b","c"};
var second = new List<string> {"x","y","z"};
var merged = first.Select(item => new { ListIndex = 1, Value = item}).ToList();
merged.AddRange(second.Select(item => new { ListIndex = 2, Value = item});
//or use concat
var merged = first.Select(item => new { ListIndex = 1, Value = item});
.Concat(second.Select(item => new { ListIndex = 2, Value = item});
或者,如果您有以下来源:
List<List<string>> lists = new List<List<string>>
{
new List<string> {"a","b","c"},
new List<string> {"x","y","z"}
};
你可以做:
var merged = lists.SelectMany((item, index) =>
item.Select(s => new { ListIndex = index, Value = s}));
请注意,这将生成一个从 0 开始的列表,所以如果您真的需要一个从 1 开始的列表,只需执行ListIndex = index +1
.
另外,如果您经常使用它,我会将其创建为特定实体,例如
struct ListIdentValue
{
public int ListIndex {get; private set;}
public string Value {get; private set;}
public ListIdentValue(int listIndex, string value) {...}
}
string[] a = { "a", "b", "c" };
string[] b = { "x", "z", "y" };
var t =
(
from ai in a
select new { listNo = 1, Item = ai }
).Union
(
from bi in b
select new { listNo = 2, Item = bi }
);
或者
var t =
(
from ai in a
select new object[] { 1, ai }
).Union
(
from bi in b
select new object[] { 2, bi }
);