考虑以下问题:
var ds = (from t1 in list1
from t2 in list2
select new {t1.Name, t2.Name}
).ToList();
返回类似于:(粗略表示)
的内容Name1, InnerName1
Name1, InnerName2
Name2, InnerName1
Name2, InnerName2
我想得到的是:
Name1, InnerName1
Null, InnerName2
Name2, InnerName1
Null, InnerName2.
含义,如果我在列表中已经有t1.Name,我想在t1的结果的其余部分使用null或空字符串。
我已经知道我可以遍历结果,但是我将它用作数据源,并希望做一些基于设置的事情。
有没有办法在单个查询中完成此操作?
答案 0 :(得分:2)
假设您使用Linq-to-Objects,您可以执行以下操作:
string previous = null;
var results =
(from t1 in list1
from t2 in list2
select new {
Name1 = (previous == t1.Name) ? null : (previous = t1.Name),
Name2 = t2.Name
})
.ToList();
但这依赖于副作用,并不是特别优雅。你可能更喜欢这样的东西:
var result =
(from t1 in list1
select
list2.Take(1)
.Select(t2 => new { Name1 = t1.Name, Name2 = t2.Name })
.Concat(list2.Skip(1)
.Select(t2 => new { Name1 = (string)null, Name2 = t2.Name }))
.SelectMany(x => x)
.ToList();
答案 1 :(得分:1)
我认为你需要在这里进行交叉连接。 试试这个。
//will get null values for both
var ds = (from t1 in list1
join t2 in list2 into t3
from objt3 in t3.DefaultIfEmpty()
select new {t1.Name, objt3.Name}
).ToList();
修改强>
//will get null values for second list
var ds = (from t1 in list1
join t2 in list2 into t3
from objt3 in t3.DefaultIfEmpty()
where t1 != null
select new {t1.Name, objt3.Name}
).ToList();
<强>更新强>
//will get null values for second list
var ds = (from t1 in list1
where t1 != null
join t2 in list2 into t3
from objt3 in t3.DefaultIfEmpty()
select new {t1.Name, objt3.Name}
).ToList();
答案 2 :(得分:1)
您可以使用以下内容,它基本上模拟了您尝试使用Aggregate
避免的循环。不幸的是,它不能再使用匿名类,因为我们需要使用Enumerable.Empty<Data>()
来开始聚合:
class Data { public string Name; public string Inner; };
// Test data
var data = new Data[]
{
new Data {Name = "Name1", Inner = "InnerName1"},
new Data {Name = "Name1", Inner = "InnerName2"},
new Data {Name = "Name2", Inner = "InnerName1"},
new Data {Name = "Name2", Inner = "InnerName2"}
};
// remove duplicate Names
var filtered = data.Aggregate(
Enumerable.Empty<Data>(),
(list, newitem) => list.Concat(new Data[] {new Data {
Name = (list.Any() && list.Last().Name == newitem.Name)
? null : newitem.Name,
Inner = newitem.Inner
}}));
答案 3 :(得分:1)
与p.s.w.g相距不远。想出来了,这不使用查询语法。它避免使用.First()
并使用Zip
。
var listResult = list1.SelectMany(x => (new[] { x, })
.Concat(Enumerable.Repeat((string)null, int.MaxValue))
.Zip(list2, (y, z) => new { Name1 = y, Name2 = z, }));
答案 4 :(得分:1)
要以不同方式处理序列中的第一项,您可以使用传入索引的Select
重载,我们可以将其与零进行比较。
在查询语法中无法访问该重载,并且查询看起来使用所有方法语法而不是混合和匹配更好。
var query = list1.SelectMany(t1 => list2.Select((t2, i) => new
{
Name1 = i == 0 ? t1.Name : null,
Name2 = t2.Name
}));