我是新来的,对C#缺乏经验。我一直在搜索MSDN文档和谷歌,但无法找到答案(我尽量尽量说出来):
我想在列表或数组中存储一个固定长度的有序整数序列,然后创建这些整数数组的数组。有谁知道我如何计算不同整数数组的数量,以及我应该使用哪些特定数据类型(List,plain array等)?我没有我一直在使用的确切代码,但这里有类似于我一直在尝试的内容:
int[] set1 = {2, 56, 8};
int[] set2 = {8, 25, 90};
int[] set3 = {2, 56, 8};
var superset = new List<int[]>;
superset.Add(set1);
superset.Add(set2);
superset.Add(set3);
Console.Out.WriteLine(superset.Distinct().Count()); // would like this to output 2, but Distinct() doesn't seem to actually work and I would get 3
答案 0 :(得分:3)
Distinct
方法有一个重载,它接受IEqualityComparer的实例。为int数组(即public class IntArrayComparer : IEqualityComparer<int[]>
)创建IEqualityComparer的实现,并将实例传递给Distinct调用。
SequenceEqual方法可能对IEqualityComparer<int[]>.Equals
的实施有所帮助,但该练习留给您。
答案 1 :(得分:3)
您只需要为整数数组创建一个Comparer类,并将其实例传递给Distinct方法。
Console.Out.WriteLine(superset.Distinct(new ArrayComparer()).Count());
以下是一个例子:
class ArrayComparer : IEqualityComparer<int[]>
{
public bool Equals(int[] x, int[] y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
if (x.Length != y.Length)
return false;
//Check whether the arrays' values are equal.
for(int i = 0; i < x.Length; i++){
if(x[i] != y[i])
return false;
}
// If got this far, arrays are equal
return true;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(int[] intArray)
{
//Check whether the object is null
if (Object.ReferenceEquals(intArray, null)) return 0;
//Calculate the hash code for the array
int hashCode = 0;
bool isFirst = true;
foreach(int i in intArray){
if(isFirst) {
hashCode = i;
isFirst = false;
}
else
{
hashCode = hashCode ^ i;
}
}
return hashCode;
}
}
这对我有用。给出你想要的结果。
答案 2 :(得分:0)
尚未发布的答案解释了为什么Distinct().Count()
返回3:原因是Distinct()
正在使用数组的默认相等比较器,它比较引用相等性。此代码将返回2:
int[] set1 = {2, 56, 8};
int[] set2 = {8, 25, 90};
int[] set3 = set1;
var superset = new List<int[]>();
superset.Add(set1);
superset.Add(set2);
superset.Add(set3);
Console.WriteLine(superset.Distinct().Count());
正如鲍勃和理查德所建议的那样,你可以通过创建IEqualityComparer<int[]>
的实现来克服这个问题,从而为你提供所需的行为。
答案 3 :(得分:0)
private int CountDistinct2DPoints(double[][] data)
{
Dictionary<Tuple<double, double>, int> pointsMap = new Dictionary<Tuple<double, double>, int>();
for(int i = 0; i < data.Length; i++)
{
if (!pointsMap.ContainsKey(Tuple.Create(data[i][0], data[i][1])))
{
pointsMap.Add(Tuple.Create(data[i][0], data[i][1]), 1);
}
else
{
pointsMap[Tuple.Create(data[i][0], data[i][1])]++;
}
}
return pointsMap.Keys.Count;
}
答案 4 :(得分:-1)
请记住一句名言:
“聪明的数据结构和愚蠢的代码比其他方式更好。” - -Eric Raymond,The Cathedral and the Bazaar
听起来这里的目标是能够使用简单而富有表现力的代码(.Distinct()
)来比较您的数据。在这种情况下,我建议从简单数组升级到更丰富的对象。像这样:
class Numbers
{
public int FirstNumber { get; set; }
public int SecondNumber { get; set; }
public int ThirdNumber { get; set; }
}
然后你可以拥有这些对象的数组,而不是数组数组。这样做的好处是,您可以赋予此对象更丰富的功能。如:
class Numbers : IEquatable<Numbers>
{
public int FirstNumber { get; set; }
public int SecondNumber { get; set; }
public int ThirdNumber { get; set; }
public bool Equals(Numbers other)
{
if (other == null)
return false;
return (
this.FirstNumber == other.FirstNumber &&
this.SecondNumber == other.SecondNumber &&
this.ThirdNumber == other.ThirdNumber
);
}
}
现在,您可以通过dumber代码更有效地使用更智能的数据类型。 (只是引用引用,不要认为它说你写的是愚蠢的代码或任何无用的代码。)这通常是首选,因为这意味着你不必重写多个比较逻辑如果需要在多个地方使用的地方。比较逻辑发生在数据类型的内部,而不是程序代码。
请注意,这是未经测试的和徒手代码。如果我在实施中遗漏了一些内容,请纠正我:)