如何对需要在Accounts
数组上排序的PersonRoles
数组进行排序,以确定关联人员与该帐户的关联角色?
例如,
Bob是帐户O
的所有者(12
),帐户CO
的共同签名者(123
)和帐户受益人{{1} }。
Joe是帐户1234
的所有者(O
)和帐户123
帐户1234
的帐户BE
。
我如何首先按照所有者(12
)的顺序为Bob {/ strong>排序Accounts
数组,然后是Co-signer(' CO&#39 ;),然后按顺序受益人(O
)。
帐户对象结构
BE
从Bob返回的Bob下列出的原始帐户数组。
Accounts
{
AccountNumber: 12,
PersonRoles: [
{
AccountRoleCode: "O",
AccountRoleDescription: "Owner",
Person: "Bob"
},
{
AccountRoleCode: "CO",
AccountRoleDescription: "Co-Signer",
Person: ""
},
{
AccountRoleCode: "BE",
AccountRoleDescription: "Beneficiary",
Person: "Joe"
},
],
Balance: 5.00
},
{
AccountNumber: 123,
PersonRoles: [
{
AccountRoleCode: "O",
AccountRoleDescription: "Owner",
Person: "Joe"
},
{
AccountRoleCode: "CO",
AccountRoleDescription: "Co-Signer",
Person: "Bob"
},
{
AccountRoleCode: "BE",
AccountRoleDescription: "Beneficiary",
Person: null
},
],
Balance: 100.00
},
{
AccountNumber: 1234,
PersonRoles: [
{
AccountRoleCode: "O",
AccountRoleDescription: "Owner",
Person: "Joe"
},
{
AccountRoleCode: "CO",
AccountRoleDescription: "Co-Signer",
Person: null
},
{
AccountRoleCode: "BE",
AccountRoleDescription: "Beneficiary",
Person: "Bob"
},
],
Balance: 10000000.00
}
所需的排序数组。
[1234, 12, 123]
我最初的方法是在阵列上使用LINQ,但我不确定如何遍历[12, 123, 1234]
然后循环遍历Accounts[]
以基于PersonRoles[]
排序在Accounts[]
。
这是否需要双LINQ查询?或者另一种方法会更好吗?
答案 0 :(得分:1)
这样的事情应该有效:
var result = accounts
.Select(a => new
{
a.AccountNumber,
RoleCodes = a.PersonRoles
.Where(r => r.Person == "Bob")
.Select(r => r.AccountRoleCode)
.ToArray(),
})
.OrderBy(a => a.RoleCodes.Select(code => GetOrderByCode(code)).Max())
.ThenBy(a => a.AccountNumber);
答案 1 :(得分:1)
这是一种方式,假设Bob在所有帐户中只有一个角色:
<input type="text" id="t1">
<input type="text" id="t2" pattern="^\d{5}$">
变化,如果Bob可以有多个角色(并且Bob在每个帐户中都有一个角色)。在这种情况下,我们首先选择正确的角色,即指定顺序中的第一个角色:
var ordered =
from a in Accounts
from r in a.PersonRoles
where r.Person == "Bob"
let ordering = r.AccountRoleCode == "O" ? 1 : r.AccountRoleCode == "CO" ? 2 : 3
orderby ordering
select a.AccountNumber;
读者的练习:如果有不涉及Bob的帐户怎么办?
答案 2 :(得分:1)
您可以使用这样的Linq语句:
var givenPerson = "Bob";
Accounts.Where(a => a.PersonRoles.SelectMany(r => r.Person).Contains(givenPerson))
.OrderBy(a => a, new CustomComparerForRoleCode(givenPerson));
要进行自定义比较以按AccountRoleCode
排序,您需要一个比较器类:
public class CustomComparerForRoleCode : IComparer<PersonRole[]>
{
public string PersonInRole { get; set; }
public CustomComparerForRoleCode(string personInRole) {
this.PersonInRole = personInRole;
}
public int Compare(PersonRole[] x, PersonRole[] y) {
var roleCode = x.First(r => r.Person == PersonInRole).AccountRoleCode;
var otherRoleCode = y.First(r => r.Person == PersonInRole).AccountRoleCode;
if (roleCode == otherRoleCode)
return 0;
switch (roleCode) {
case "O":
return 1;
case "BE":
return -1;
case "CO":
if (otherRoleCode == "O")
return -1;
return 1;
}
}
}
这假定一个人每个帐户只能有一个角色。根据需要进行调整。
答案 3 :(得分:1)
public class AccountsByNameComparer : IComparer<Account>
{
private readonly string _name;
public AccountsByNameComparer(string name)
{
_name = name;
}
public int Compare(Account x, Account y)
{
return AccountSortValue(x).CompareTo(AccountSortValue(y));
}
private int AccountSortValue(Account account)
{
if (account.PersonRoles.Any(role => role.AccountRoleCode == "O"
&& role.Name == _name)) return 0;
if (account.PersonRoles.Any(role => role.AccountRoleCode == "CO"
&& role.Name == _name)) return 1;
if (account.PersonRoles.Any(role => role.AccountRoleCode == "BE"
&& role.Name == _name)) return 2;
return 3;
}
}
现在你可以做到
accounts.Sort(new AccountsByNameComparer("Bob"));
或
var sorted = accounts.OrderBy(a => a, new AccountsByNameComparer("Bob"));
这样做的好处是
这是一个令人遗憾的漫长而复杂的单元测试。但是你必须验证它是否以某种方式工作,这通常比实际运行整个应用程序更容易。
[TestClass]
public class SortAccountsByNameTests
{
[TestMethod]
public void AccountsAreSortedInCorrectOrder()
{
var account1 = new Account
{
PersonRoles = new PersonRole[]
{
new PersonRole {AccountRoleCode = "BE", Name = "Bob"},
new PersonRole {AccountRoleCode = "CO", Name = "Steve"},
new PersonRole {AccountRoleCode = "O", Name = "John"},
}
};
var account2 = new Account
{
PersonRoles = new PersonRole[]
{
new PersonRole {AccountRoleCode = "CO", Name = "Bob"},
new PersonRole {AccountRoleCode = "O", Name = "Steve"},
new PersonRole {AccountRoleCode = "BE", Name = "John"},
}
};
var account3 = new Account
{
PersonRoles = new PersonRole[]
{
new PersonRole {AccountRoleCode = "O", Name = "Bob"},
new PersonRole {AccountRoleCode = "CO", Name = "Steve"},
new PersonRole {AccountRoleCode = "BE", Name = "John"},
}
};
var account4 = new Account
{
PersonRoles = new PersonRole[]
{
new PersonRole {AccountRoleCode = "O", Name = "Al"},
new PersonRole {AccountRoleCode = "CO", Name = "Steve"},
new PersonRole {AccountRoleCode = "BE", Name = "John"},
}
};
var unsorted = new Account[] {account1, account2, account3, account4};
var comparer = new AccountsByNameComparer("Bob");
var sorted = unsorted.OrderBy(a => a, comparer);
var expectedOrder = new Account[]{account3, account2, account1, account4};
Assert.IsTrue(expectedOrder.SequenceEqual(sorted));
}
}
我现在要被带走了。如果要在不重写整个比较器的情况下更改排序顺序,该怎么办?或者你不喜欢那些if
陈述? (对不起,这是令人讨厌和无用的。为什么我这样做?)
public class AccountsByNameComparer : IComparer<Account>
{
private readonly string _name;
private readonly List<string> _preferredRoleSequence;
public AccountsByNameComparer(string name, IEnumerable<string> preferredRoleSequence)
{
_name = name;
_preferredRoleSequence = preferredRoleSequence.ToList();
}
public int Compare(Account x, Account y)
{
return AccountSortValue(x).CompareTo(AccountSortValue(y));
}
private int AccountSortValue(Account account)
{
var rolesMatchedByName = account.PersonRoles
.Where(role => role.Name == _name);
var preferredRoleMatches =
rolesMatchedByName.Select(role =>
_preferredRoleSequence.IndexOf(role.AccountRoleCode))
.Where(index => index > -1)
.ToArray();
if (preferredRoleMatches.Any())
return preferredRoleMatches.Min();
return Int32.MaxValue;
}
}
public class ExecutiveAccountsByNameComparer : AccountsByNameComparer
{
public ExecutiveAccountsByNameComparer(string name)
:base(name, new []{"O", "CO", "BE" }) { }
}