在整数列表中找到重复项的最佳方法是什么(无论它处于什么位置)?我不需要代码只是解决这个问题的最佳方法(在C#中)。
例如:
List<List<int>> TestData = new List<List<int>>
{
new List<int> { 1, 2, 3 },
new List<int> { 2, 1, 3 },
new List<int> { 6, 8, 3, 45,48 },
new List<int> { 9, 2, 4 },
new List<int> { 9, 2, 4, 15 },
};
这个想法是,这将返回
Count | Set
----------------
2x | 1,2,3
1x | 6, 8, 3, 45, 48
1x | 9,2,4
1x | 9, 2, 4, 15
我一直在忽视这个看似非常简单的问题,但出于某种原因,我无法弄明白。希望有人能够提供帮助,就像我说的代码没有必要但非常感激。
答案 0 :(得分:6)
好吧,首先要将列表转换为集合,
var testSets = testData.Select(s => new HashSet<int>(s));
然后您可以将集合分组以实现相等。
var groupedSets = testSets.GroupBy(s => s, HashSet<int>.CreateSetComparer());
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
public static void Main()
{
var testData = new List<List<int>>
{
new List<int> { 1, 2, 3 },
new List<int> { 2, 1, 3 },
new List<int> { 6, 8, 3, 45, 48 },
new List<int> { 9, 2, 4 },
new List<int> { 9, 2, 4, 15 }
};
var testSets = testData.Select(s => new HashSet<int>(s));
var groupedSets = testSets.GroupBy(s => s, HashSet<int>.CreateSetComparer());
foreach(var g in groupedSets)
{
var setString = String.Join(", ", g.Key);
Console.WriteLine($" {g.Count()} | {setString}");
}
}
}
答案 1 :(得分:0)
您应该使用适当的数据结构来强制执行您的要求。在这种情况下,您有一个tots字典:
IDictionary<ISet<int>, int>
如果您不想使用LINQ(这可能是最佳实践,请参阅其他答案),您可以按如下方式构建它:
var result = new Dictionary<HashSet<int>, int>();
foreach (var i in TestData)
{
var key = new HashSet<int>(i);
int count;
result.TryGetValue(key, out count);
result[id] = count + 1;
}
答案 2 :(得分:0)
请尝试以下操作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<List<int>> TestData = new List<List<int>>
{
new List<int> { 1, 2, 3 },
new List<int> { 2, 1, 3 },
new List<int> { 6, 8, 3 },
new List<int> { 9, 2, 4 },
};
var values = TestData.SelectMany(x => x).GroupBy(x => x).ToList();
var counts = values.Select(x => new { value = x.Key, times = x.Count() }).ToList();
var times = counts.GroupBy(x => x.times).Select(x => new { key = x.Key, values = x.Select(y => y.value).ToList() }).OrderBy(x => x.key).ToList();
}
}
}
答案 3 :(得分:0)
The answer of @Jodrell is very elegant (for me is the best), but only say depends of what you want the answer is correct For the nex data var testData = new List<List<int>> { new List<int> { 1, 2, 3 }, new List<int> { 1, 2, 3 }, new List<int> { 1, 2, 3, 3 }, } The result is going to be: Count | Set 3x | 1,2,3 And not the next: Count | Set 2x | 1,2,3 1x | 1,2,3,3 So depends of your question... Ok, so, with the last one this is my code, is not fancy and you can improve a lot of things
enter code here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestListInt
{
class Program
{
public class WrapperListInt
{
public List<int> list;
public WrapperListInt(List<int> list)
{
this.list = list;
}
public override int GetHashCode()
{
return 0;
}
public override bool Equals(object obj)
{
if (this == obj) return true;
WrapperListInt o = obj as WrapperListInt;
if (this.list.Count != o.list.Count) return false;
for (int i = 0; i < this.list.Count; i++)
{
if (this.list[i] != o.list[i]) { return false; }
}
return true;
}
}
public Program() {
var testData = new List<List<int>>
{
new List<int> { 1, 2, 3 },
new List<int> { 1, 3, 2 },
new List<int> { 1, 2, 3, 3 },
new List<int> { 6, 8, 3, 45,48 },
new List<int> { 9, 2, 15, 4 },
new List<int> { 9, 2, 4},
new List<int> { 9, 2, 4, 15 }
};
//Order every list
foreach (var td in testData)
{
td.Sort();
}
Dictionary<WrapperListInt, int> dic = new Dictionary<WrapperListInt, int>();
foreach (var listInt in testData)
{
WrapperListInt aux = new WrapperListInt(listInt);
int countList;
if (dic.TryGetValue(aux, out countList))
{
dic[aux]++;
}
else
{
dic.Add(aux, 1);
}
}
foreach (var d in dic)
{
var setString = String.Join(", ", d.Key.list);
Console.WriteLine($" {d.Value} | {setString}");
}
}
static void Main(string[] args)
{
new Program();
}
}
}