2012-04-03 4 views
3

Я имею в виду хороший способ, чтобы найти различия в двух спискахНахождение различия в двух списках

здесь проблема:

Два списка есть несколько строк, где первые 3 цифры/символы (* разделителями) представляют уникальный ключ (за ним следует текст String = "key1 * key2 * key3 * text").

здесь строка Пример:

AA1*1D*4*The quick brown fox*****CC*3456321234543~ 

где "* AA1 * 1D * 4 *" является уникальным ключом

List1: "index1 * index2 * index3", «index2 * index2 * index3" , "index3 * index2 * index3"

List2: "index2 * index2 * index3", "index1 * index2 * index3", "index3 * index2 * index3", "index4 * index2 * index3"

Мне нужно сопоставить индексы в обоих списках и сравнить их.

  1. Если все 3 индексы от 1 списка матча 3 индексов из другого списка, мне нужно отслеживать обе строки записи в новом списке

  2. Если есть множество индексов в одном списке, что дон» t появляется в другом, мне нужно отслеживать одну сторону и сохранять пустую запись на другой стороне. (# 4 в приведенном выше примере)

возвращают список

Это то, что я сделал до сих пор, но я вроде изо всех сил здесь:

 List<String> Base = baseListCopy.Except(resultListCopy, StringComparer.InvariantCultureIgnoreCase).ToList(); //Keep unique values(keep differences in lists) 
     List<String> Result = resultListCopy.Except(baseListCopy, StringComparer.InvariantCultureIgnoreCase).ToList(); //Keep unique values (keep differences in lists) 

     List<String[]> blocksComparison = new List<String[]>(); //we container for non-matching blocks; so we could output them later 

     //if both reports have same amount of blocks 
     if ((Result.Count > 0 || Base.Count > 0) && (Result.Count == Base.Count)) 
     { 
      foreach (String S in Result) 
      { 
       String[] sArr = S.Split('*'); 
       foreach (String B in Base) 
       { 
        String[] bArr = B.Split('*'); 

        if (sArr[0].Equals(bArr[0]) && sArr[1].Equals(bArr[1]) && sArr[2].Equals(bArr[2]) && sArr[3].Equals(bArr[3])) 
        { 
         String[] NA = new String[2]; //keep results 
         NA[0] = B; //[0] for base 
         NA[1] = S; //[1] for result 
         blocksComparison.Add(NA); 
         break; 
        } 
       } 
      } 
     } 

могли бы вы предложить хороший алгоритм для этого процесса?

Thank you

+4

Я хотел бы сказать, что с помощью составной строковый ключ вместо пользовательского класса для различных индексов является источник вашей проблемы. – Oded

+0

Если я прав, может ли эта проблема быть разбита на -> найти пересечение двух списков? Я спрашиваю, почему порядок индекса имеет значение? – noMAD

ответ

1

Если я правильно понимаю ваш вопрос, вы хотите, чтобы иметь возможность сравнить элементы их префиксом «ключ», а не по всему содержимому строки. Если это так, реализация пользовательского сопоставления равенства позволит вам легко использовать алгоритмы набора LINQ.

Эта программа ...

class EqCmp : IEqualityComparer<string> { 

    public bool Equals(string x, string y) { 
     return GetKey(x).SequenceEqual(GetKey(y)); 
    } 

    public int GetHashCode(string obj) { 
     // Using Sum could cause OverflowException. 
     return GetKey(obj).Aggregate(0, (sum, subkey) => sum + subkey.GetHashCode()); 
    } 

    static IEnumerable<string> GetKey(string line) { 
     // If we just split to 3 strings, the last one could exceed the key, so we split to 4. 
     // This is not the most efficient way, but is simple. 
     return line.Split(new[] { '*' }, 4).Take(3); 
    } 

} 

class Program { 

    static void Main(string[] args) { 

     var l1 = new List<string> { 
      "index1*index1*index1*some text", 
      "index1*index1*index2*some text ** test test test", 
      "index1*index2*index1*some text", 
      "index1*index2*index2*some text", 
      "index2*index1*index1*some text" 
     }; 

     var l2 = new List<string> { 
      "index1*index1*index2*some text ** test test test", 
      "index2*index1*index1*some text", 
      "index2*index1*index2*some text" 
     }; 

     var eq = new EqCmp(); 

     Console.WriteLine("Elements that are both in l1 and l2:"); 
     foreach (var line in l1.Intersect(l2, eq)) 
      Console.WriteLine(line); 

     Console.WriteLine("\nElements that are in l1 but not in l2:"); 
     foreach (var line in l1.Except(l2, eq)) 
      Console.WriteLine(line); 

     // Etc... 

    } 

} 

... печатает следующий результат:

Elements that are both in l1 and l2: 
index1*index1*index2*some text ** test test test 
index2*index1*index1*some text 

Elements that are in l1 but not in l2: 
index1*index1*index1*some text 
index1*index2*index1*some text 
index1*index2*index2*some text 
3

Вы можете использовать HashSet.

Создайте HashSet для List1. помните index1 * index2 * index3 отличается от index3 * index2 * index1.

Теперь перебираем второй список.

Create Hashset for List1. 

foreach(string in list2) 
{ 
    if(hashset contains string) 
     //Add it to the new list. 
} 
1
List one = new List(); 
List two = new List(); 
List three = new List(); 
HashMap<String,Integer> intersect = new HashMap<String,Integer>(); 

for(one: String index) 
{ 
    intersect.put(index.next,intersect.get(index.next) + 1); 
} 

for(two: String index) 
{ 
    if(intersect.containsKey(index.next)) 
    { 
     three.add(index.next); 
    } 
} 
Смежные вопросы