[英]Compare a set of three strings with another
我正在根據一些數據制作一個唯一的“ 3個字符串集”列表,這樣的話,如果3個字符串在一起,它們就會變成一個集合,而我的列表中只能有唯一的集合。
而且,如果集在列表中尚不存在,我會繼續將其添加到列表中,這樣,如果我遇到這三個字符串{A,B,C},我就不會再將其放入列表中。 所以我有兩個問題 。 第二個答案的答案實際上取決於第一個答案。
我正在使用C#。
數組或列表都是存儲數據的最佳選擇,因為正如gomoimo在評論中所述,將它們串聯意味着您丟失了可能需要的數據。 舉個例子,串聯在一起的“ ab”,“ cd”,“ ef”與串聯的“ abcd”,“ e”和“ f”是相同的,但不應視為等效集。
為了比較它們,我將按字母順序對列表進行排序,然后按順序比較每個值。 這就考慮了值的順序無關緊要的事實。 偽代碼示例可能如下所示:
Compare(List<string> a, List<string> b) { a.Sort(); b.Sort(); if(a.Length == b.Length) { for(int i = 0; i < a.Length; i++) { if(a[i] != b[i]) { return false; } } return true; } else { return false; } }
既然您在評論中說過,性能是一個重要的考慮因素,因為您可能要比較數百萬個這樣的集合,而且集合中不會有重復的元素,這是我代碼的更優化版本,請注意,我沒有不再需要對兩個列表進行排序,這將節省執行該功能的大量時間。
Compare(List<string> a, List<string> b)
{
if(a.Length == b.Length)
{
for(int i = 0; i < a.Length; i++)
{
if(!b.Contains(a[i]))
{
return false;
}
}
return true;
}
else
{
return false;
}
}
DrewJordan使用哈希表的方法可能仍然比我的方法好,因為它只需要對三個一組進行排序,然后可以比我的方法快得多地與現有集進行比較。
這是一個簡單的字符串包裝器:
/// The wrapper for three strings
public class StringTriplet
{
private List<string> Store;
// accessors to three source strings:
public string A { get; private set; }
public string B { get; private set; }
public string C { get; private set; }
// constructor (need to feel internal storage)
public StringTriplet(string a, string b, string c)
{
this.Store = new List<string>();
this.Store.Add(a);
this.Store.Add(b);
this.Store.Add(c);
// sort is reqiured, cause later we don't want to compare all strings each other
this.Store.Sort();
this.A = a;
this.B = b;
this.C = c;
}
// additional method. you could add IComparable declaration to the entire class, but it is not necessary in your task...
public int CompareTo(StringTriplet obj)
{
if (null == obj)
return -1;
int cmp;
cmp = this.Store.Count.CompareTo(obj.Store.Count);
if (0 != cmp)
return cmp;
for (int i = 0; i < this.Store.Count; i++)
{
if (null == this.Store[i])
return 1;
cmp = this.Store[i].CompareTo(obj.Store[i]);
if ( 0 != cmp )
return cmp;
}
return 0;
}
// additional method. it is a good practice : override both 'Equals' and 'GetHashCode'. See below..
override public bool Equals(object obj)
{
if (! (obj is StringTriplet))
return false;
var t = obj as StringTriplet;
return ( 0 == this.CompareTo(t));
}
// necessary method . it will be implicitly used on adding values to the HashSet
public override int GetHashCode()
{
int res = 0;
for (int i = 0; i < this.Store.Count; i++)
res = res ^ (null == this.Store[i] ? 0 : this.Store[i].GetHashCode()) ^ i;
return res;
}
}
現在您可以創建哈希集並添加值:
var t = new HashSet<StringTriplet> ();
t.Add (new StringTriplet ("a", "b", "c"));
t.Add (new StringTriplet ("a", "b1", "c"));
t.Add (new StringTriplet ("a", "b", "c")); // dup
t.Add (new StringTriplet ("a", "c", "b")); // dup
t.Add (new StringTriplet ("1", "2", "3"));
t.Add (new StringTriplet ("1", "2", "4"));
t.Add (new StringTriplet ("3", "2", "1"));
foreach (var s in t) {
Console.WriteLine (s.A + " " + s.B + " " + s.C);
}
return 0;
您可以繼承List<String>
並重寫Equals()
和GetHashCode()
方法:
public class StringList : List<String>
{
public override bool Equals(object obj)
{
StringList other = obj as StringList;
if (other == null) return false;
return this.All(x => other.Contains(x));
}
public override int GetHashCode()
{
unchecked
{
int hash = 19;
foreach (String s in this)
{
hash = hash + s.GetHashCode() * 31;
}
return hash;
}
}
}
現在,您可以使用HashSet<StringList>
僅存儲唯一的集合
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.