2013-09-07 4 views
0

Я хочу сохранить дублированные значения массива, или что то же самое, что я хочу удалить уникальные имена.Удалить уникальные значения массива с помощью LINQ?

Например, если у меня есть массив с таким содержимым:

{a, b, c, c, c} 

Я хочу, чтобы хранить это в другом массиве:

{c, c, c} 

Я знаю, как выполнить операцию с использованием для цикла, но Я хочу улучшить код с помощью LINQ-расширений (если возможно).

+0

Таким образом, исходный массив просто держит '{а, Ь}', даже не один ' c'? Кроме того, сортируется вход? Каковы требования к производительности? (Потому что, если производительность - это какой-то фактор, я предлагаю цикл + 'Array.Resize') – sehe

+0

@sehe, действительно независимо от того, сохраняет ли первый массив C или нет, в то время как новый массив содержит дублируемое значение 1 раз, да массив сортировка, как я уже сказал, я не предпочитаю использовать Для того, чтобы он использовал LINQ-расширения для улучшения, спасибо за комментарий. – ElektroStudios

ответ

2

Это делает то, что вы хотите, но измените порядок элементов в своей первоначальной коллекции.

var query = yourArray.GroupBy(x=>x) 
    .Where(x=>x.Count() > 1) 
    .SelectMany(x=>x) 
    .ToArray(); 

Чтобы получить разницу между этими двумя, вы можете использовать Кроме этого, выполнив:

var exceptResult = yourArray.Except(query); 
+0

Да, это то, что я имел в виду для «не-исполнителей». Тем не менее, несколько беспомощных котят производительности плачут тихо в углу. Действительно, при сортировке ввода простой алгоритм с одним проходом был бы намного более эффективным и, возможно, более понятным ... – sehe

+0

@sehe Хорошо, я согласен, что эта проблема не требует LINQ. Но так как он попросил решение LINQ, я предоставил его :) Этого должно быть достаточно, чтобы иметь замечание о производительности в комментариях, чтобы помнить всех, что это не идеальный способ сделать это. – Save

+0

Я пробовал что-то вроде array1.except (array1 .distinct), но не работает, я прокомментирую это, потому что, если у вас есть идея повышения производительности с использованием linq, вы, ребята, считаете, что в массиве, который может содержать около 100 записей (НЕ БОЛЬШЕ) с использованием кода @Save, может быть слишком много отрицательная точка производительности? – ElektroStudios

1

(C#) это гораздо быстрее, реализация затем делает GroupBy/Где/SelectMany (и Count(), который перечисляет). Но я должен согласиться, что это больше кода ;-)

var array = new[] { 1, 2, 3, 3, 3 }; 
var valueCounter = new ValueCounter<int>(array); 
var query = valueCounter.Where(p => p.Value > 1) 
    .SelectMany(p => Enumerable.Repeat(p.Key, p.Value)).ToArray(); 

Используя этот ValueCounter класс:

public class ValueCounter<T> : IEnumerable<KeyValuePair<T, int>> 
{ 
    private readonly IEqualityComparer<T> _comparer; 
    private readonly Dictionary<T, int> _valueCounter; 
    private int _nullCount = 0; 

    public ValueCounter(IEnumerable<T> values, IEqualityComparer<T> comparer) 
    { 
     _comparer = comparer ?? EqualityComparer<T>.Default; 
     _valueCounter = new Dictionary<T, int>(_comparer); 
     if (values != null) 
     { 
      foreach (var value in values) 
      { 
       Add(value); 
      } 
     } 
    } 

    public ValueCounter(IEqualityComparer<T> comparer) 
     : this(null, comparer) 
    { 
    } 

    public ValueCounter(IEnumerable<T> values) 
     : this(values, null) 
    { 
    } 

    public ValueCounter() 
     : this(null, null) 
    { 
    } 

    public void Add(T value) 
    { 
     if (value == null) 
     { 
      _nullCount++; 
     } 
     else 
     { 
      int count; 
      if (_valueCounter.TryGetValue(value, out count)) 
      { 
       _valueCounter[value] = count + 1; 
      } 
      else 
      { 
       _valueCounter.Add(value, 1); 
      } 
     } 
    } 

    /// <summary> 
    /// Removes a value 
    /// </summary> 
    /// <param name="value">The value that needs to be removed</param> 
    /// <returns>True if a value was removed</returns> 
    public bool Remove(T value) 
    { 
     if (value == null) 
     { 
      if (_nullCount > 0) 
      { 
       _nullCount--; 
       return true; 
      } 
     } 
     else 
     { 
      int count; 
      if (_valueCounter.TryGetValue(value, out count)) 
      { 
       if (count == 1) 
       { 
        _valueCounter.Remove(value); 
       } 
       else 
       { 
        _valueCounter[value] = count - 1; 
       } 
       return true; 
      } 
     } 
     return false; 
    } 

    public int GetCount(T value) 
    { 
     int result; 
     _valueCounter.TryGetValue(value, out result); 
     return result; 
    } 

    public IEnumerator<KeyValuePair<T, int>> GetEnumerator() 
    { 
     return _valueCounter.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 
Смежные вопросы