我刚问了另一个问题here,答案就在那里。
但这解决了本质上是语法问题的问题。现在我需要实际解决方案的帮助。
这是与上一个问题相同的代码(已修复并添加了内容)。
XElement FILE1 = XElement.Load (@"..\FILE1.XML");
XElement FILE2 = XElement.Load (@"..\FILE2.XML");
var orders = from file1 in FILE1.Descendants("Players").Elements("Player")
select new {
name=new {
clientID=ulm.Element("ClientID").Value,
firstName=file1.Element("FirstName").Value,
lastName=file1.Element("LastName").Value
}
};
var orders2 =
from file2 in FILE2.Descendants("Players").Elements("Player")
select new {
name=new {
clientID=ulm.Element("ClientID").Value,
firstName=file2.Element("FirstName").Value,
lastName=file2.Element("LastName").Value
}
};
var matchingResults = from i in orders from j in orders2 where (i.name.firstName==j.name.firstName && i.name.lastName==j.name.lastName)
select i;
matchingResults.Dump()
为了让它变得有趣,我在尝试匹配它们之前为每个序列结果添加了一个ClientID。
我需要知道的是来自orders2的玩家节点中的订单EXISTS的玩家节点。还是不存在?理想情况下,我也可以选择NOT EXISTS / EXISTS检查的选择标准。 (LastName,或FirstName&& LastName,或仅限ClientID等)
我没有想法如何解决这个问题。谢谢你的帮助。
答案 0 :(得分:0)
Enumerable.Intersect
或Enumerable.Except
为了能够选择选择标准,您可以创建参数化IEqualityComparer<Client>
。
class Client
{
public string ClientID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
[Flags]
enum Criteria {
ClientID, FirstName, LastName
}
class ClientEqualityComparer : IEqualityComparer<Client> {
private Criteria criteria;
public ClientEqualityComparer(Criteria criteria) {
this.criteria = criteria;
}
#region IEqualityComparer<Client> Membres
public bool Equals(Client x, Client y)
{
if (criteria.HasFlag(Criteria.ClientID) && x.ClientID != y.ClientID)
return false;
if (criteria.HasFlag(Criteria.FirstName) && x.FirstName != y.FirstName)
return false;
if (criteria.HasFlag(Criteria.LastName) && x.LastName != y.LastName)
return false;
return true;
}
public int GetHashCode(Client obj)
{
int hash = 17;
if (criteria.HasFlag(Criteria.ClientID))
hash = hash * 31 + obj.ClientID;
if (criteria.HasFlag(Criteria.FirstName))
hash = hash * 31 + obj.FirstName;
if (criteria.HasFlag(Criteria.LastName))
hash = hash * 31 + obj.LastName;
}
#endregion
}
static void Main(string[] args)
{
IEnumerable<Client> orders;
IEnumerable<Client> orders2;
//...
var matchingIdFn = orders.Intersect(orders2,
new ClientEqualityComparer(Criteria.ClientID | Criteria.FirstName));
var matchingIdFnLn = orders.Intersect(orders2,
new ClientEqualityComparer(Criteria.ClientID | Criteria.FirstName | Criteria.LastName));
var different = orders.Except(orders2, new ClientEqualityComparer(Criteria.ClientID | Criteria.FirstName));
}
var orders = from file1 in FILE1.Descendants("Players").Elements("Player")
select new Client{
ClientID=ulm.Element("ClientID").Value,
FirstName=file1.Element("FirstName").Value,
LastName=file1.Element("LastName").Value
};
答案 1 :(得分:0)
我的第二个Ahmed KRAIEM建议使用Intersect
或Except
这是另一个让你可以使用任意lambda进行比较的解决方案:
void Main()
{
XElement FILE1 = XElement.Parse(
@"<Root>
<Players>
<Player><ClientId>1</ClientId><FirstName>Bob</FirstName><LastName>Smith</LastName></Player>
<Player><ClientId>2</ClientId><FirstName>John</FirstName><LastName>Smith</LastName></Player>
</Players>
</Root>");
XElement FILE2 = XElement.Parse(
@"<Root>
<Players>
<Player><ClientId>2</ClientId><FirstName>Bob</FirstName><LastName>Smith</LastName></Player>
<Player><ClientId>3</ClientId><FirstName>Mike</FirstName><LastName>Smith</LastName></Player>
</Players>
</Root>");
var orders = from file1 in FILE1.Descendants("Players").Elements("Player")
select new Player(Int32.Parse(file1.Element("ClientId").Value), file1.Element("FirstName").Value, file1.Element("LastName").Value);
var orders2 = from file2 in FILE2.Descendants("Players").Elements("Player")
select new Player(Int32.Parse(file2.Element("ClientId").Value), file2.Element("FirstName").Value, file2.Element("LastName").Value);
//orders.Dump();
//orders2.Dump();
var exists = orders2.Intersect(orders, new LambdaEqualityComparer<Player>((i, j) => i.FirstName == j.FirstName && i.LastName == j.LastName));
// or
//var exists = orders2.Intersect(orders, new LambdaEqualityComparer<Player>((i, j) => i.ClientId == j.ClientId));
exists.Dump();
var notExists = orders2.Except(orders, new LambdaEqualityComparer<Player>((i, j) => i.FirstName == j.FirstName && i.LastName == j.LastName));
// or
//var notExists = orders2.Except(orders, new LambdaEqualityComparer<Player>((i, j) => i.ClientId == j.ClientId));
notExists.Dump();
}
public class Player
{
public int ClientId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Player(int clientId, string firstName, string lastName)
{
ClientId = clientId;
FirstName = firstName;
LastName = lastName;
}
}
public class LambdaEqualityComparer<T> : IEqualityComparer<T>
{
private Func<T, T, bool> EqualityComparer { get; set; }
public LambdaEqualityComparer(Func<T, T, bool> equalityComparer)
{
EqualityComparer = equalityComparer;
}
public bool Equals(T x, T y)
{
return EqualityComparer(x, y);
}
public int GetHashCode(T obj)
{
// If the hash codes are different, then Equals never gets called. Make sure Equals is always called by making sure the hash codes are always the same.
// (Underneath, the .NET code is using a set and the not (!) of a Find method to determine if the set doesn't already contain the item and should be added.
// Find is not bothering to call Equals unless it finds a hash code that matches.)
//return obj.GetHashCode();
return 0;
}
}
请注意,如果您不想创建Player
对象,则可以将其完全删除,在orders
和orders2
中填充匿名对象,就像之前一样,并创建一个new LambdaEqualityComparer<dynamic>
而不是new LambdaEqualityComparer<Player>
,但由于动态反射调用会慢一些。