我想在集合中找到类似的对象,具体取决于我实施的方法
例如此示例类:
class myObj
{
public int Data1 { get; set; }
public int Data2 { get; set; }
public int Data3 { get; set; }
}
然后在类中实现类似方法:
public bool Similar(myObj obj)
{
if (obj.Data1 == this.Data1 && obj.Data2 == this.Data2)
return true;
return false;
}
现在我有这个系列:
List<myObj> items = new List<myObj>();
// none similar
items.Add(new myObj() { Data1 = 1, Data2 = 2, Data3 = 4 });
items.Add(new myObj() { Data1 = 2, Data2 = 3, Data3 = 18 });
items.Add(new myObj() { Data1 = 3, Data2 = 4, Data3 = 75 });
items.Add(new myObj() { Data1 = 4, Data2 = 2, Data3 = 3 });
//similar
items.Add(new myObj() { Data1 = 5, Data2 = 26, Data3 = 97 });
items.Add(new myObj() { Data1 = 5, Data2 = 26, Data3 = 37 });
items.Add(new myObj() { Data1 = 10, Data2 = 45, Data3 = 47 });
items.Add(new myObj() { Data1 = 10, Data2 = 45, Data3 = 19 });
获取我做过的类似对象:
private static List<myObj> GetSimilars(List<myObj> items)
{
List<myObj> similars = new List<myObj>();
while (items.Count > 0)
{
var q = (from c in items
where c.Similar(items[0])
select c).ToList();
if (q.Count > 1)
{
similars.AddRange(q);
foreach (var obj in q)
items.Remove(obj);
}
else
items.Remove(items[0]);
}
return similars;
}
有更好的方法吗?
答案 0 :(得分:2)
试试这个:
private static List<myObj> GetSimilars(List<myObj> items)
{
return items.SelectMany(x => items.Where(z => x != z && x.Similar(z))).ToList();
}
或者如果你喜欢这个:
private static List<myObj> GetSimilars(List<myObj> items)
{
var result = from x in items
from y in items
where x != y && x.Similar(y)
select x;
return result.ToList();
}
答案 1 :(得分:2)
您可以使用Linq的GroupBy
和SelectMany
:
var similarGroups = from i in items
group i by new { i.Data1, i.Data2 } into D1D2Group
where D1D2Group.Count() > 1
select D1D2Group;
foreach (var grp in similarGroups)
Console.WriteLine("DataGroup:{0}/{1} Count:{2}"
, grp.Key.Data1
, grp.Key.Data2
, grp.Count());
如果您希望将群组展平为List<myObj>
,请GetSimilars
:
List <myObj> similars = similarGroups.SelectMany(g => g).ToList();
答案 2 :(得分:2)
如何制作可重复使用的课程。
public class MyObjSimilarity : EqualityComparer<myObj>
{
public override bool Equals(myObj a, myObj b)
{
if (obj.Data1 == this.Data1 && obj.Data2 == this.Data2)
{
return true;
}
return false;
}
public override int GetHashCode(myObj o)
{
int hash = 17;
hash = hash * 23 + o.Data1.GetHashCode();
hash = hash * 23 + o.Data2.GetHashCode();
return hash;
}
}
你可以这样使用,
var similarity = new MyObjSimilarity();
items.Where(o => similarity.Equals(o, w));
或传入字典的构造函数,
var similarity = new MyObjSimilarity();
var lookup = new Dictionary<myObj, string>(similarity);
或GroupBy
var similarity = new MyObjSimilarity();
items.GroupBy(o => o, o => o, similarity);
或者像其他答案一样
var similarity = new MyObjSimilarity();
items.GroupBy(
o => o,
o => new { Instance = o, Count = Count(o) },
similarity);
或在其他框架友好的地方。
答案 3 :(得分:1)
return
items.Where(w => items.Count(c => c.Similar(w)) > 1)
/* add .Distinct() optional*/
.ToList();
答案 4 :(得分:1)
您可以实现接口IComparable或使用自编写的比较器,它实现IComparer。如果你这样做,你可以对你的对象的列表进行排序。
答案 5 :(得分:1)
要考虑在调用GetSimilars时修改项目列表的示例中的副作用,您必须执行此操作。为了摆脱副作用,松开了RemoveAll()
private static List<myObj> GetSimilars(List<myObj> items)
{
var similars = from s in items
where items.Any(s2 => s != s2 && s.Similar(s2))
select s;
items.RemoveAll(s => similars.Contains(s));
return similars.ToList();
}
答案 6 :(得分:0)
使用groupBy来点击,您可以根据第一个和第二个值对项目进行分组,如下所示......
var GroupByValues=items.GroupBy(obj=> new { val1 = obj.Data1,val2=obj.Data2 });
然后您可以遍历该组以获取值...