簡體   English   中英

從 C# 中的列表中選擇唯一元素

[英]Selecting Unique Elements From a List in C#

如何從列表{0, 1, 2, 2, 2, 3, 4, 4, 5}中選擇唯一元素,以便我得到{0, 1, 3, 5} ,有效地刪除重復的所有實例元素{2, 4}

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 }
var nums = new int{ 0...4,4,5};
var distinct = nums.Distinct();

確保您使用的是 Linq 和 .NET 框架 3.5。

與 lambda..

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);

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;
    }
}

如果您的 List 中有復雜類型的對象並且想要獲取屬性的唯一值,這是另一種可行的方法:

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();
    }
}

如果 Linq 對您不可用,因為您必須支持無法升級的舊代碼,則聲明一個 Dictionary,其中第一個 int 是數字,第二個 int 是出現次數。 循環瀏覽您的列表,加載您的字典。 完成后,循環瀏覽您的字典,僅選擇出現次數為 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;
 }

給貓剝皮的方法有很多,但 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

這是一個沒有 LINQ 的解決方案:

var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };

// This assumes the numbers are sorted
var noRepeats = new List<int>();
int temp = numbers[0]; // Or .First() if using IEnumerable
var count = 1;
for(int i = 1; i < numbers.Length; i++) // Or foreach (var n in numbers.Skip(1)) if using IEnumerable
{
    if (numbers[i] == temp) count++;
    else
    {
        if(count == 1) noRepeats.Add(temp);
        temp = numbers[i];
        count = 1;
    }
}
if(count == 1) noRepeats.Add(temp);

Console.WriteLine($"[{string.Join(separator: ",", values: numbers)}] -> [{string.Join(separator: ",", values: noRepeats)}]");

這打印:

[0,1,2,2,2,3,4,4,5] -> [0,1,3,5]

在 .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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM