我有以下两种类型的两个列表(两者都是更复杂类型的紧凑版本):
class Person
{
public Guid ID {get; set;}
public Account PrivateAccount { get; set; }
public Account SharedAccount { get; set; }
}
class Account
{
public Guid AccountId {get; set;}
public decimal Amount { get; set; }
}
我还创建了以下类型:
class PersonWithAmounts
{
public Guid PersonID {get; set;}
public decimal PAmount { get; set; }
public decimal SAmount { get; set; }
}
保存4种查询的结果:
Person
,PrivateAccount
且无SharedAccount
。
Person
没有PrivateAccount
且SharedAccount
。
Person
同时包含PrivateAccount
和SharedAccount
。
Person
s没有PrivateAccount
且没有SharedAccount
。
以下是查询:
var PAccount = (from person in PersonList
where person.PrivateAccount != null
join account in accountList on person.PrivateAccount.AccountId equals account.AccountId
select new PersonWithAmounts { PersonID = person.ID, PAmount = account.Amount })
.ToList();
var SAccount = (from person in PersonList
where person.SharedAccount != null
join account in accountList on person.SharedAccount.AccountId equals account.AccountId
select new PersonWithAmounts {PersonID = person.ID, SAmount = account.Amount })
.ToList();
var noAccount = (from person in PersonList
where person.PrivateAccount == null && person.SharedAccount == null
select new PersonWithAmounts { PersonID = person.ID })
.ToList();
我有一种感觉,我将它们合并到一个列表中的操作很复杂,并且不需要,并且想知道如何使它更具可读性(并且可能更高效):
var resultGroup = PAccount
.Concat(SAccount)
.Concat(noAccount)
.GroupBy(p => p.PersonID)
.Select(p => new PersonWithAmounts
{
PersonID = p.Key,
PAmount = p.Select(a => a.PAmount).ElementAt(0),
SAmount = p.Select(a => a.SAmount).Count() > 1 ?
p.Select(a => a.SAmount).ElementAt(1) :
p.Select(a => a.SAmount).ElementAt(0)
})
.ToList();
注意:给出了3个列表,我必须使用它们(对于任何想知道原因的人,我使用的是Dynamics CRM及其LINQ提供程序,不能使用作为常规的,所以我需要坚持非常简单的查询。)
澄清
PersonWithAmounts
是由我创建的类,因此它不是强制性的。Person
。最后的查询(resultGroup
)实现了它,但是作为评论,我对GroupBy
的结果顺序做了一个有问题的假设。resultGroup
的结果应包括PersonList
(上述4种类型)的所有记录。我认为链接的例子证明了这一点。
<!DOCTYPE HTML []>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="Generator" content="LINQ to XML, baby!" />
<style type="text/css">
body {
margin: 0.3em 0.3em 0.4em 0.4em;
font-family: Verdana;
font-size: 80%;
background: white
}
p, pre {
margin:0;
padding:0;
font-family: Verdana;
}
table {
border-collapse: collapse;
border: 2px solid #17b;
margin: 0.3em 0.2em;
}
table.limit {
border-bottom-color: #c31;
}
table.expandable {
border-bottom-style: dashed;
}
table.error {
border-bottom-width: 4px;
}
td, th {
vertical-align: top;
border: 1px solid #aaa;
padding: 0.1em 0.2em;
margin: 0;
}
th {
text-align: left;
background-color: #ddd;
border: 1px solid #777;
font-family: tahoma;
font-size:90%;
font-weight: bold;
}
th.member {
padding: 0.1em 0.2em 0.1em 0.2em;
}
td.typeheader {
font-family: tahoma;
font-size: 100%;
font-weight: bold;
background-color: #17b;
color: white;
padding: 0 0.2em 0.15em 0.1em;
}
td.n { text-align: right }
a:link.typeheader, a:visited.typeheader, a:link.extenser, a:visited.extenser, a:link.fixedextenser, a:visited.fixedextenser {
font-family: tahoma;
font-size: 90%;
font-weight: bold;
text-decoration: none;
background-color: #17b;
color: white;
float:left;
}
a:link.extenser, a:visited.extenser, a:link.fixedextenser, a:visited.fixedextenser {
float:right;
padding-left:2pt;
margin-left:4pt
}
span.typeglyph, span.typeglyphx {
padding: 0 0.2em 0 0;
margin: 0;
}
span.extenser, span.extenserx, span.fixedextenser {
margin-top:1.2pt;
}
span.typeglyph, span.extenser, span.fixedextenser {
font-family: webdings;
}
span.fixedextenser {
display:none;
position:fixed;
right:6px;
}
td.typeheader:hover .fixedextenser {
display:block
}
span.typeglyphx, span.extenserx {
font-family: arial;
font-weight: bold;
margin: 2px;
}
table.group {
border: none;
margin: 0;
}
td.group {
border: none;
padding: 0 0.1em;
}
div.spacer { margin: 0.6em 0; }
table.headingpresenter {
border: none;
border-left: 3px dotted #1a5;
margin: 1em 0em 1.2em 0.15em;
}
th.headingpresenter {
font-family: Arial;
border: none;
padding: 0 0 0.2em 0.5em;
background-color: white;
color: green;
font-size: 110%;
}
td.headingpresenter {
border: none;
padding: 0 0 0 0.6em;
}
td.summary {
background-color: #def;
color: #024;
font-family: Tahoma;
padding: 0 0.1em 0.1em 0.1em;
}
td.columntotal {
font-family: Tahoma;
background-color: #eee;
font-weight: bold;
color: #17b;
font-size:90%;
text-align:right;
}
span.graphbar {
background: #17b;
color: #17b;
margin-left: -2px;
margin-right: -2px;
}
a:link.graphcolumn, a:visited.graphcolumn {
color: #17b;
text-decoration: none;
font-weight: bold;
font-family: Arial;
font-size: 110%;
letter-spacing: -0.2em;
margin-left: 0.3em;
margin-right: 0.1em;
}
a:link.collection, a:visited.collection { color:green }
a:link.reference, a:visited.reference { color:blue }
i { color: green }
em { color:red; }
span.highlight { background: #ff8 }
code { font-family: Consolas }
code.xml b { color:blue; font-weight:normal }
code.xml i { color:maroon; font-weight:normal; font-style:normal }
code.xml em { color:red; font-weight:normal; font-style:normal }
</style>
</head>
<body><div class="spacer"><table id="t1"><tr><td class="typeheader" colspan="3">List<Person> (4 items)<span class="fixedextenser">4</span></td></tr><tr><th title="System.Guid">ID</th><th title="UserQuery+Account">PrivateAccount</th><th title="UserQuery+Account">SharedAccount</th></tr><tr><td>ab65bd04-1789-462d-88b5-6a99ab3ded35</td><td><table id="t2"><tr><td class="typeheader" colspan="2">Account<span class="fixedextenser">4</span></td></tr><tr id="sum3"><td colspan="2" class="summary">UserQuery+Account</td></tr><tr><th class="member" title="System.Guid">AccountId</th><td>aaaaaaaa-4525-4bfe-9e2c-a7afff0dda1f</td></tr><tr><th class="member" title="System.Decimal">Amount</th><td>100</td></tr></table></td><td><i>null</i></td></tr><tr><td>594e4a34-be98-479f-b5b5-91bb29aff98e</td><td><i>null</i></td><td><table id="t4"><tr><td class="typeheader" colspan="2">Account<span class="fixedextenser">4</span></td></tr><tr id="sum5"><td colspan="2" class="summary">UserQuery+Account</td></tr><tr><th class="member" title="System.Guid">AccountId</th><td>eeeeeeee-4525-4bfe-9e2c-a7afff0dda1f</td></tr><tr><th class="member" title="System.Decimal">Amount</th><td>2000</td></tr></table></td></tr><tr><td>d6735efe-2c4b-4e87-a0cb-7aaf9539994f</td><td><table id="t6"><tr><td class="typeheader" colspan="2">Account<span class="fixedextenser">4</span></td></tr><tr id="sum7"><td colspan="2" class="summary">UserQuery+Account</td></tr><tr><th class="member" title="System.Guid">AccountId</th><td>cccccccc-4525-4bfe-9e2c-a7afff0dda1f</td></tr><tr><th class="member" title="System.Decimal">Amount</th><td>300</td></tr></table></td><td><table id="t8"><tr><td class="typeheader" colspan="2">Account<span class="fixedextenser">4</span></td></tr><tr id="sum9"><td colspan="2" class="summary">UserQuery+Account</td></tr><tr><th class="member" title="System.Guid">AccountId</th><td>ffffffff-4525-4bfe-9e2c-a7afff0dda1f</td></tr><tr><th class="member" title="System.Decimal">Amount</th><td>3000</td></tr></table></td></tr><tr><td>dad6db35-ed55-49b1-a9ff-4ddb1a3a2989</td><td><i>null</i></td><td><i>null</i></td></tr></table></div><div class="spacer"><table id="t10"><tr><td class="typeheader" colspan="3">List<PersonWithAmounts> (4 items)<span class="fixedextenser">4</span></td></tr><tr><th title="System.Guid">PersonID</th><th title="System.Decimal">PAmount</th><th title="System.Decimal">SAmount</th></tr><tr><td>ab65bd04-1789-462d-88b5-6a99ab3ded35</td><td class="n">100</td><td class="n">0</td></tr><tr><td>d6735efe-2c4b-4e87-a0cb-7aaf9539994f</td><td class="n">300</td><td class="n">3000</td></tr><tr><td>594e4a34-be98-479f-b5b5-91bb29aff98e</td><td class="n">0</td><td class="n">2000</td></tr><tr><td>dad6db35-ed55-49b1-a9ff-4ddb1a3a2989</td><td class="n">0</td><td class="n">0</td></tr><tr><td title="Totals" class="columntotal"></td><td title="Total=400
Average=100" class="columntotal">400</td><td title="Total=5000
Average=1250" class="columntotal">5000</td></tr></table></div></body>
</html>
答案 0 :(得分:0)
假设3个查询是为了表示无法更改的3个列表,我建议最简单的解决方案是提取组合答案所需的部分:
var PAccountOnly = from p in PAccount where p.SharedAccount == null select p;
var SAccountOnly = from s in SAccount where s.PrivateAccount == null select s;
var PandSAccounts = from p in PAccount
join s in SAccount on p.PersonID equals s.PersonID
select new PersonWithAmounts { PersonID = p.PersonID, PAmount = p.PAmount, SAmount = s.SAmount };
var allAccounts = PAccountOnly.Concat(SAccountOnly).Concat(PandSAccounts).Concat(noAccount).ToList();