




var nums = new int{ 0...4,4,5};
var distinct = nums.Distinct();
убедитесь, что вы используете Linq и .NET framework 3.5.
Это возвращает {0, 1, 2, 3, 4, 5}, включая повторяющиеся элементы.
О, моя ошибка. Я не заметил, что вы хотите удалить эти повторяющиеся записи.
var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };
var uniqueNumbers =
from n in numbers
group n by n into nGroup
where nGroup.Count() == 1
select nGroup.Key;
// { 0, 1, 3, 5 }
МОЙ БОГ. Это необычно. Как насчет HashSet <int> r = new HashSet <int> (числа);
@Tymek: OP хочет удалить дубликаты, оставив только те числа, которые уникальны в исходной последовательности.
Я заблудился. Предоставленный вами код не изменяет исходную последовательность, называемую «числами».
@Tymek: OP попросил выбрать уникальные числа, что подразумевает создание новой последовательности путем изучения существующей последовательности.
В данном случае я не понимаю вашего первого комментария. Это то, что сделал бы HashSet, если бы вы создали его из показанной вами переменной «числа». Он будет содержать только уникальные значения: 0,1,2,3,4,5. : /
Ха! Я понял это теперь! {0,1,2,2,2,3,4,4,5} -> {0, 3}, а не {0,1,2,3,4,5}
@Tymek: Очень близко. Это будет {0, 1, 3, 5}, поскольку повторяются только 2 и 4. Но я думаю, вы уловили идею.
Если Linq вам недоступен, потому что вам нужно поддерживать устаревший код, который нельзя обновить, объявите Dictionary, где первое int - это число, а второе int - количество вхождений. Прокрутите список, загрузив словарь. Когда вы закончите, прокрутите свой Словарь, выбирая только те элементы, у которых количество вхождений равно 1.
Решение C# 2.0:
static IEnumerable<T> GetUniques<T>(IEnumerable<T> things)
{
Dictionary<T, int> counts = new Dictionary<T, int>();
foreach (T item in things)
{
int count;
if (counts.TryGetValue(item, out count))
counts[item] = ++count;
else
counts.Add(item, 1);
}
foreach (KeyValuePair<T, int> kvp in counts)
{
if (kvp.Value == 1)
yield return kvp.Key;
}
}
Это вызовет исключение KeyNotFoundException
Это работает, но вам нужно изменить counts [item] ++; в if (counts.ContainsKey (item)) counts [item] ++; иначе считается. Добавить (элемент, 1);
Я считаю, что Мэтт хотел сказать:
static IEnumerable<T> GetUniques<T>(IEnumerable<T> things)
{
Dictionary<T, bool> uniques = new Dictionary<T, bool>();
foreach (T item in things)
{
if (!(uniques.ContainsKey(item)))
{
uniques.Add(item, true);
}
}
return uniques.Keys;
}
Это версия .NET 2.0 того, что опубликовал CVertex. Он также возвращает повторяющиеся элементы.
Нет, я предпочитаю оставить их (как говорили французы, англичане иногда стреляли в адмирала) для поощрения l'autres.
С лямбдой ..
var all = new[] {0,1,1,2,3,4,4,4,5,6,7,8,8}.ToList();
var unique = all.GroupBy(i => i).Where(i => i.Count() == 1).Select(i=>i.Key);
Обратите внимание, что для использования этого решения с объектами, где вы хотите получить список объектов с определенным ключом / полем, который уникален, вам необходимо заменить последний Select на SelectMany: .SelectMany(i => i), который сгладит IEnumerable<IGrouping<TKey, TElement>> обратно. к IEnumerable<T>.
Еще один способ сделать это с объектами или иным образом - полностью заменить Where и Select на .Select(x => x.FirstOrDefault()) (позаимствовано из это сообщение в блоге).
В .Net 2.0 я почти уверен в этом решении:
public IEnumerable<T> Distinct<T>(IEnumerable<T> source)
{
List<T> uniques = new List<T>();
foreach (T item in source)
{
if (!uniques.Contains(item)) uniques.Add(item);
}
return uniques;
}
Но этот метод добавляет каждую текущую стоимость. Он этого не хочет. Он хочет, чтобы повторяющиеся значения были ПОЛНОСТЬЮ УДАЛЕНЫ.
Вот еще один способ, который работает, если у вас есть объекты сложного типа в вашем списке и вы хотите получить уникальные значения свойства:
var uniqueValues= myItems.Select(k => k.MyProperty)
.GroupBy(g => g)
.Where(c => c.Count() == 1)
.Select(k => k.Key)
.ToList();
Или получить отличные значения:
var distinctValues = myItems.Select(p => p.MyProperty)
.Distinct()
.ToList();
Если ваше свойство также является сложным типом, вы можете создать собственный компаратор для Distinct (), например Distinct (OrderComparer), где OrderComparer может выглядеть так:
public class OrderComparer : IEqualityComparer<Order>
{
public bool Equals(Order o1, Order o2)
{
return o1.OrderID == o2.OrderID;
}
public int GetHashCode(Order obj)
{
return obj.OrderID.GetHashCode();
}
}
мне это понравилось больше. короче и легче читать (субъективно?) с лямбда-выражениями.
@EwaldStieger, он не хочет оставлять один экземпляр для каждого значения, он хочет УДАЛИТЬ ВСЕ ЭКЗЕМПЛЯРЫ значений, которые присутствуют более 1 раза. Так как же Distinct() может этого добиться? (Меня удивили 8 голосов, поскольку ваш ответ не решает проблему правильно.)
@MassimilianoKraus Да, вы правы. Я пропустил это в своем исходном ответе и обновил его сейчас
Есть много способов снять шкуру с кошки, но HashSet, похоже, предназначен для этой задачи.
var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };
HashSet<int> r = new HashSet<int>(numbers);
foreach( int i in r ) {
Console.Write( "{0} ", i );
}
Выход:
0 1 2 3 4 5
Спасибо, но я хотел удалить все экземпляры повторяющихся элементов из исходный список, например. {0, 1, 1, 2, 2, 3} -> {0, 3}
Как это объект класса List, который вы хотите изменить?
По крайней мере, за пределами C# (я не могу сказать о самом C#) начальная точка на самом деле не является набором, если он содержит дубликаты. Это может быть несколько наборов, или список, или ...