2013-10-01 2 views
1

У меня есть много данных из базы данных, которые являются результатом функции поиска. Теперь у меня есть List<string[]>, который имеет дублированные элементы типа string[]. Результатом поиска являются string[].C# удалить дубликаты из списка <string[]>

Я знаю, что каждый новый созданный массив имеет другой экземпляр, поэтому я не могу использовать MyListOfArrays.Distinct().ToList().

Может быть, это очень простой вопрос ...

Мой вопрос, есть ли какие-либо функции, встроенные в удалить дублированный string[] форму List<string[]>? Или я должен написать это своим самолюбием?

Спасибо

+4

Любые усилия, до сих пор? –

+7

Вы можете использовать '.Distinct()' с пользовательским 'EqualityComparer': http://stackoverflow.com/questions/4607485/linq-distinct-use-delegate-for-equality-comparer – valverij

+6

Хотя не прямой ответ на ваш вопрос вопрос, возможно, лучше изменить запрос из базы данных, чтобы он не дал вам дубликатов результатов в его наборе результатов. –

ответ

3

Вы можете использовать distinct с пользовательскими equalityComparer

IEnumerable<string[]> distinct = inputStringArrayList.Distinct(new EqualityComparer()); 

EqualityComparer

class EqualityComparer : IEqualityComparer<string[]> 
{ 
    public bool Equals(string[] x, string[] y) 
    { 
     if (x.Length != y.Length) 
     { 
      return false; 
     } 
     if (x.Where((t, i) => t != y[i]).Any()) 
     { 
      return false; 
     } 
     return true; 
    } 

    public int GetHashCode(string[] obj) 
    { 
     return obj.GetHashCode(); 
    } 
} 

Альтернативный метод Equals

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

Здесь я предполагаю, что вы имеете те же самые строковые массивы с одинаковым содержанием в одном индексе.

Коррекция от Matthew Watson

public int GetHashCode(string[] obj) 
     { 
      if (obj == null) 
       return 0; 

      int hash = 17; 

      unchecked 
      { 
       foreach (string s in obj) 
        hash = hash*23 + ((s == null) ? 0 : s.GetHashCode()); 
      } 

      return hash; 
     } 
+3

Я боюсь, что это не сработает, потому что 'GetHashCode()' возвращает разные значения даже для идентичных последовательностей. –

+0

Является ли GetHashCode реализованным в классе Array? –

+0

Да, я получил тот же список после выполнения этой функции. – Patrick

1

Простой и не очень эффективным подходом было бы использовать string.Join на string[]: метод

list = list 
.GroupBy(strArr => string.Join("|", strArr)) 
.Select(g => g.First()) 
.ToList(); 
+2

У этого могут быть проблемы, если строки имеют значения '|' в них. В соответствии с этим '{" a | b "}' равно '{" a "," b "}'. – Servy

+0

@Servy: Да, это то, что я имел в виду с «простым». Может быть достаточно или нет. Поэтому, если вход не является произвольным, вы можете выбрать разделитель, который не может произойти. –

+1

Я хочу сказать, что это не просто медленно. Если это всегда было правильным, но возможно медленным, вам нужно было иметь дело только с большими объемами данных. Когда это не всегда правильно, вопрос о том, может ли он использоваться в любом конкретном случае, гораздо больше. – Servy

2

я исправил ответ от @Muctadir Динара.

(Он заслуживает похвалы за ответ - я просто исправить ее и обеспечивая полную тестовую программу):

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace Demo 
{ 
    sealed class EqualityComparer: IEqualityComparer<string[]> 
    { 
     public bool Equals(string[] x, string[] y) 
     { 
      if (ReferenceEquals(x, y)) 
       return true; 

      if (x == null || y == null) 
       return false; 

      return x.SequenceEqual(y); 
     } 

     public int GetHashCode(string[] obj) 
     { 
      if (obj == null) 
       return 0; 

      int hash = 17; 

      unchecked 
      { 
       foreach (string s in obj) 
        hash = hash*23 + ((s == null) ? 0 : s.GetHashCode()); 
      } 

      return hash; 
     } 
    } 

    class Program 
    { 
     private void run() 
     { 
      var list = new List<string[]> 
      { 
       strings(1, 10), 
       strings(2, 10), 
       strings(3, 10), 
       strings(2, 10), 
       strings(4, 10) 
      }; 

      dump(list); 
      Console.WriteLine(); 

      var result = list.Distinct(new EqualityComparer()); 
      dump(result); 
     } 

     static void dump(IEnumerable<string[]> list) 
     { 
      foreach (var array in list) 
       Console.WriteLine(string.Join(",", array)); 
     } 

     static string[] strings(int start, int count) 
     { 
      return Enumerable.Range(start, count) 
       .Select(element => element.ToString()) 
       .ToArray(); 
     } 

     static void Main(string[] args) 
     { 
      new Program().run(); 
     } 
    } 
} 
+0

Очень приятно. Спасибо, что это работает. Изменить: Принято ответ Muctadir Dinar. – Patrick

+0

@Patrick Почему вы принимаете полностью неправильный ответ с несколькими серьезными ошибками, которые мешают ему работать, и для этого потребуются нетривиальные изменения? – Servy

+0

@Servy Моя вина за то, что он сказал: «Он заслуживает доверия за ответ», я думаю. ;) Я сказал, что потому, что не хотел «украсть» идею предоставления реализации IEqualityComparer. –

Смежные вопросы