下面是我们尝试根据以下OR
条件对记录进行分组的记录:
LINQ中是否有一种方法可以使Group By
条件的Or
?
Name Email Phone Id
--- --------- ------------ ----------
Rohan rohan@s.com NULL 1
R. Mehta rohan@s.com 9999999999 2
Alex alex@j.com 7777777777 3
Lisa John john@j.com 6666666666 4
Lisa lisa@j.com 6666666666 5
Siri siri@s.com NULL 6
RM info@s.com 9999999999 7
Lisa NULL NULL 8
Lisa John m@s.com 7777777757 9
预期输出
Group 1:
Key: Rohan
RecordIds: 1,2,7 (As `Id:1` has same email as `Id:2`, `Id:2` has same
phone number as `Id:7`.)
Group 2:
Key: Lisa John
RecordIds: 4,5,8,9 (As `Id:4` has same phone number as `Id:5`. While `Id:5`
has the same name as `Id:8`. As `Id:9` has the same name
as `Id: 4`, include that)
如果记录9具有电子邮件ID:rohan@s.com
,则:
输出
Group 1:
Key: Rohan
RecordIds: 1,2,7,4,5,8,9
注意::输入为SQL table
,将通过LINQ to SQL
进行读取。因此,也必须考虑查询性能。
原始解决方案:
以下是一种肮脏的解决方案:
var gl-1
var gl-2
var gl-3
gl-1
中获取每个结果,以检查id
,gl-2
中是否存在相应的gl-3
。如果是这样,请在ids
gl-1
gl-2
中获取每个结果,以检查id
中的任何结果中是否存在对应的gl-1
,因此,将独占的ids
包含到gl-1
记录中。如果循环遇到gl-1
中不存在的结果,请将其作为结果包含在gl-1
中。gl-3
执行步骤5。答案 0 :(得分:2)
GroupBy
需要对“平等”进行一些定义。您可以使用所需的逻辑 定义一个EqualityComparer
,但结果会不一致。您的分组破坏了分组所需的相等性的传递属性。换句话说,如果A=B
和B=C
,则A=C
必须为真。
例如,以下几对项将在同一组中(“相等”):
A, B, C and A, D, E
A, D, E and F, G, E
但是
A, B, C and F, G, E
不会在同一组中。
要获得所需的输出(例如,多个组中的第9项),您需要使用标准循环来递归地找到与第一个“相等”的所有项,然后再找到与该组“相等”的所有项,则所有与第三组“相等”的项目都以此类推,以此类推。Linq在这里并不是很有用(除非可能是在每个递归调用中进行搜索)。
答案 1 :(得分:0)
Linq查询是线性运行的,这意味着一旦它通过了一个新的可能的组,就无法返回并使用它。
让我们假设
public class aperson
{
public string Name;
public string Email;
public string Phone;
public int ID;
public aperson(string name,string email,string phone,int id)
{
Name = name;
Email = email;
Phone = phone;
ID = id;
}
}
示例
new aperson("a","a@","1",1),
new aperson("b","b@","2",2),
new aperson("a","c@","2",3)
迭代1:使用(“ a”,“ a @”,“ 1”)值创建组1
迭代2:使用(“ b”,“ b @”,“ 2”)值创建组2
迭代3:在这里,系统必须将其与组1或组2分组,但不能同时分组。
要解决此问题,您的迭代器必须回到第2组和第1组并加入它们。
要解决此问题,您必须将其分为几步。
步骤1。创建组
步骤2。按创建的组分组。
我认为有更好的方法可以做到这一点。我只是在说明流程中该问题的处理方式以及原因。
解决方案代码
public static Dictionary<string, int> group = new Dictionary<string, int>();
public static void adduniquevalue(aperson person,int id)
{
if (person.Email != null && !group.Keys.Contains(person.Email))
{
group.Add(person.Email, id);
}
if (person.Phone != null && !group.Keys.Contains(person.Phone))
{
group.Add(person.Phone, id);
}
if (person.Name != null && !group.Keys.Contains(person.Name))
{
group.Add(person.Name, id);
}
}
public static void CreateGroupKeys(aperson person)
{
int id = group.Count;
List<int> groupmatches = new List<int>();
if (person.Email != null && group.Keys.Contains(person.Email))
groupmatches.Add(group[person.Email]);
if (person.Phone != null && group.Keys.Contains(person.Phone))
groupmatches.Add(group[person.Phone]);
if (person.Name != null && group.Keys.Contains(person.Name))
groupmatches.Add(group[person.Name]);
if (groupmatches.GroupBy(x=>x).Count() > 1)
{
int newid = groupmatches[0];
group.Keys.Where(key => groupmatches.Contains(group[key]))
.ToList()
.ForEach(key => { group[key] = newid; });
}
if (groupmatches.Count == 0)
adduniquevalue(person, id);
else adduniquevalue(person, groupmatches[0]);
}
public static int GetGroupKey(aperson person)
{
if (person.Email != null && group.Keys.Contains(person.Email))
return group[person.Email];
if (person.Phone != null && group.Keys.Contains(person.Phone))
return group[person.Phone];
if (person.Name != null && group.Keys.Contains(person.Name))
return group[person.Name];
else return 0;
}
这将在字典中创建组,以后您可以在普通组中使用该方法。
像这样:
people.ForEach(x => CreateGroupKeys(x));
var groups = people.GroupBy(x => GetGroupKey(x)).ToList();