List<dynamic> a = new List<dynamic>();
a.Add(new { Foo = 1, Baz = "Inga", Name = "Alice"});
a.Add(new { Foo = 2, Baz = "Baz", Name = "Bob"});
a.Add(new { Foo = 3, Baz = "Hi", Name = "Charlie"});
List<dynamic> b = new List<dynamic>();
b.Add(new { Foo = 1, Value = "Bar", Code = "A"});
b.Add(new { Foo = 1, Value = "Quux", Code = "B"});
b.Add(new { Foo = 2, Value = "Bar", Code = "C"});
b.Add(new { Foo = 3, Value = "Mint", Code = "A"});
b.Add(new { Foo = 3, Value = "Seven", Code = "Q"});
b.Add(new { Foo = 3, Value = "Threeve", Code = "T"});
好的....所以我有一个问题(自然) 这是设计和简化的,专注于手头的问题。 我需要修改Linq查询以将两个列表投影到以下响应:
[
{ Foo = 1
, Baz = "Inga"
, Code = "A"
, Bars = [{ Value = "Bar", Code = "A"}
,{ Value = "Quux", Code = "B"}
]
}
,{ Foo = 2
, Baz = "Baz"
, Code = "C"
, Bars = [{ Value = "Fizz", Code = "C"}]
}
,{ Foo = 3
, Baz = "Hi"
, Code = "A"
, Bars = [{ Value = "Mint", Code = "A"}
,{ Value = "Seven", Code = "Q"}
,{ Value = "Threeve", Code = "T"}
]
}
]
有没有办法查询集合b来选择
(b.First Where Distinct By b.Foo) AsEnumerable()
?
我需要选择a
的投影,但在实现时,确定列表Code
中的第一个b
b.Foo == a.Foo
并放置b.Code
直接在a
。然后是b中的b.Foo == a.Foo
需要放入a.Bars
的项目。
我手上的问题是我没有识别单a
因此我无法预先选择a
和b
值来简化这个混乱,并且没有机会重塑。
所以,如果我想搜索Where Value = Bar
;需要使用正确的映射和投影返回Alice和Bob。
天真的尝试将是......
var results = a.Join( b
, master => master.Foo
, detail => detail.Foo
, (master, detail) => new { master, detail})
.Select(item => new
{
item.master.Foo
, item.master.Baz
, item.master.Name
, item.detail.Code
, Bars = b.Select(x => x.Foo.Equals(item.master.Foo))
};
但是这导致我的结果包含重复的“Alice”记录和重复的“Charlie”记录,因为它内部加入了a和b。我真正想做的事(伪)是
a.Join(
b.Where(b.Foo.Equals(a.Foo)).First()
, master => master.Foo
, detail => detail.Foo
, (master, detail) => new { master, detail}
)
.Select(item => new
{
item.master.Foo
, item.master.Baz
, item.master.Name
, item.detail.Code
, Bars = b.Select(x => x.Foo.Equals(item.master.Foo))
};
但无论我尝试什么,它都会变得一团糟。
...注意,我不能采用天真的方法,然后运行
DistinctBy
,因为投影是匿名的。
任何人都可以使用Linq to Object查询解决这个问题吗? (注意:我不需要单次通过决议)
答案 0 :(得分:2)
我会坚持将第二组(在此处表示为b
)分组,然后使用与find配对的组合投影。
var results = b.GroupBy( d => d.Foo ).Select( g => new {
Foo = g.Key,
Baz = a.First( i => i.Foo == g.Key ).Baz,
Code = g.First().Code,
Bars = g.Select( e => new { Value = e.Value, Code = e.Code }).ToArray()
});
答案 1 :(得分:1)
如果我理解正确,单个结果条目中的Code
只是第一个加入的Code
元素的b
。
所以试试这个:
var result = a.GroupJoin(b,
a0 => a0.Foo,
b0 => b0.Foo,
(a0, bs) =>
new
{
Foo = a0.Foo,
Baz = a0.Baz,
Code = bs.Select(b1 => b1.Code).FirstOrDefault(),
Bars = bs.Select(b1 => new {b1.Value, b1.Code}).ToArray()
}).ToArray();
答案 2 :(得分:0)
GroupJoin就是你需要的。您可以将Join
视为SelectMany
而GroupJoin
- 与Select
一样。不同之处在于投影的第二个参数的类型 - TInner
的{{1}}和Join
的{{1}}。在LINQ语法中,IEnumerable<TInner>
由GroupJoin
子句实现。
尽管如此,以下是两种语法中的示例:
GroupJoin
答案 3 :(得分:0)
var query = from ai in a
let bs = b.Where(bi => bi.Foo == ai.Foo)
select new
{
ai.Foo,
ai.Baz,
Code = bs.Select(bi => bi.Code).FirstOrDefault(),
Bars = bs.Select(bi => new { bi.Value, bi.Code }),
};