配列の重複した値を保存したい、または同じものを一意の名前を削除したい。
たとえば、次の内容の配列がある場合:
{a, b, c, c, c}
これを他の配列に保存したい:
{c, c, c}
For ループを使用して操作を実行する方法は知っていますが、LINQ 拡張機能を使用してコードを改善したいと考えています (可能な場合)。
配列の重複した値を保存したい、または同じものを一意の名前を削除したい。
たとえば、次の内容の配列がある場合:
{a, b, c, c, c}
これを他の配列に保存したい:
{c, c, c}
For ループを使用して操作を実行する方法は知っていますが、LINQ 拡張機能を使用してコードを改善したいと考えています (可能な場合)。
これはあなたが望むことですが、元のコレクションの要素を並べ替えます。
var query = yourArray.GroupBy(x=>x)
.Where(x=>x.Count() > 1)
.SelectMany(x=>x)
.ToArray();
2 つの違いを得るには、Except を使用して次のようにします。
var exceptResult = yourArray.Except(query);
(C# の場合) これは、GroupBy/Where/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();
}
}