我有一个锯齿状的字符串阵列,我需要找到所有独特的行。例如,对于例如查找锯齿状阵列的独特行
[
["A","B"] ,
["C","D","E"],
["B", "A"],
["E","A"]
]
这应该返回行1和行3作为行0和行2是重复的。如何才能做到这一点?我可以使用hashets吗?
我有一个锯齿状的字符串阵列,我需要找到所有独特的行。例如,对于例如查找锯齿状阵列的独特行
[
["A","B"] ,
["C","D","E"],
["B", "A"],
["E","A"]
]
这应该返回行1和行3作为行0和行2是重复的。如何才能做到这一点?我可以使用hashets吗?
首先,作为数组,行0和行2不重复。他们只有一套相同的元素。但是,如果你只是想删除这些样行,你可以这样做:
string[][] GetNonDuplicates(string[][] jagged)
{
//not a hashset, but a dictionary. A value of false means that the row
//is not duplicate, a value of true means that at least one dulicate was found
Dictionary<string[], bool> dict =
new Dictionary<string[], bool>(new RowEqualityComparer());
foreach(string[] row in jagged)
{
//if a duplicate is found - using the hash and the compare method
if (dict.ContainsKey(row))
{
dict[row] = true; //set value to true
}
else
{
dict.Add(row, false); //first time we see this row, add it
}
}
//just pop out all the keys which have a value of false
string[][] result = dict.Where(item => !item.Value)
.Select(item => item.Key)
.ToArray();
return result;
}
...
string[][] jagged = new []{new []{"A","B"} ,
new []{"C","D","E"},
new []{"B", "A"},
new []{"E","A"}};
string[][] nonDuplicates = GetNonDuplicates(jagged);
其中RowEqualityComparer
是:
class RowEqualityComparer : IEqualityComparer<string[]>
{
public bool Equals(string[] first, string[] second)
{
// different legths - different rows
if (first.Length != second.Length)
return false;
//we need to copy the arrays because Array.Sort
//will change the original rows
var flist = first.ToList();
flist.Sort();
var slist = second.ToList();
slist.Sort();
//loop and compare one by one
for (int i=0; i < flist.Count; i++)
{
if (flist[i]!=slist[i])
return false;
}
return true;
}
public int GetHashCode(string[] row)
{
//I have no idea what I'm doing, just some generic hash code calculation
if (row.Length == 0)
return 0;
int hash = row[0].GetHashCode();
for (int i = 1; i < row.Length; i++)
hash ^= row[i].GetHashCode();
return hash;
}
}
我假设不仅顺序是无关紧要的,而且当数组中的重复项不计算时('HashSet'将消除它们),'Length'也没有意义。 –
我正在设想[A,B,B]和[A,A,B]会被认为是不同的。在这种情况下,这种比较是有道理的。否则,HashSet将是一个正确的方法。 – SWeko
至于算法解去,我倒是
如果你这样做,你应该能够完成O(m * n个* LG电子(n))的其中米是你行的长度,ñ是您的要求行数
鉴于值集意味着相等,您可以对每行的单元格进行排序以帮助您对行列表进行排序。这将导致O(n * m * lg(m)+ m * n * lg(n))
你可以发表一些例子吗? – annantDev
我会计算每行的哈希值如下:
[
["A","B"] , // hash of this row :10 as example
["C","D","E"], // hash of this row : 20
["B", "A"], // hash of this row would be 10 as well
["E","A"]
]
因为它们都是字符串,所以可以计算哈希值并为每行创建一个哈希值。
您可以使用HashSet的方式如下,每行创建一个哈希集,然后找到每行其他行的差异,如果差异是空的,那么它们是相同的。
也可以使用交点,如果交点不为空,那么该行不是唯一的。
假设您想忽略顺序,重复项(因为您已经提到了HashSet
),并且结果应该只包含没有重复项的数组。
您可以实现自定义IEqualityComparer<String[]>
为Enumerable.GroupBy
并仅选择都有它独特阵列(组数== 1):
class IgnoreOrderComparer : IEqualityComparer<string[]>
{
public bool Equals(string[] x, string[] y)
{
if (x == null || y == null) return false;
return !x.Distinct().Except(y.Distinct()).Any();
}
public int GetHashCode(string[] arr)
{
if (arr == null) return int.MinValue;
int hash = 19;
foreach (string s in arr.Distinct())
{
hash = hash + s.GetHashCode();
}
return hash;
}
}
其余部分很简单:
String[][] uniques = arrays.GroupBy(arr => arr, new IgnoreOrderComparer())
.Where(g => g.Count() == 1)
.Select(g => g.First())
.ToArray();
编辑 :下面是使用同一比较器的可能更高效的版本:
IEqualityComparer<string[]> comparer = new IgnoreOrderComparer();
String[][] uniques = arrays.Where(a1 =>
!arrays.Any(a2 => a1 != a2 && comparer.Equals(a1, a2)))
.ToArray();
作为数组,第0行和第2行不重复。他们只有一套相同的元素。 – SWeko
是的,你可以使用HashSet。为每个行创建一个包装类型,或者使用IEqualityComparer和[HashSet构造函数](http://msdn.microsoft.com/zh-cn/library/bb359438.aspx)。 (确保使用所需的业务规则:例如,在计算散列值或检查序列相等之前先排序。) – 2012-12-26 22:32:27
(即使不使用HashSet,也会创建[IEqualityComparer](http://msdn.microsoft.com/zh-cn/ us/library/ms132151.aspx)可能是明智的,可以与需要测试每个业务规则的“相等”的其他方法一起使用。) – 2012-12-26 22:39:20