簡體   English   中英

如何從列表中刪除不同的值?

[英]How to remove Distinct values from a list?

我只想使用 LINQ 從列表中刪除不同的值

我的代碼-

List<MyStudents> studentsList = new List<MyStudents>();

public class MyStudents
{
     private string student;
     private int age;

     public string Student
     {
         get { return student; }
         set { student = value; }
     }

     public int Age
     {
         get { return age; }
         set { age = value; }
     }
}

我試過了-

studentsList.RemoveAll(o => o.Student).Distinct();

但這不起作用並顯示錯誤-

無法將 Lambda 表達式轉換為預期委托,因為塊中的某些返回類型不能隱式轉換為委托返回類型

PN:我更喜歡從現有列表中刪除不同的項目,而不是創建具有不同值的新列表

如果您已經為Student實現了EqualsGetHashCode ,您可以嘗試Linq GroupBy后跟SelectMany

 studentsList = studentsList
   .GroupBy(o => o.Student)            // Groups of same students
   .Where(group => group.Count() >= 2) // Students appear at least twice
   .SelectMany(group => group)         // Ungroup (flatten) to IEnumerable<Student> 
   .ToList();                          // Materialized as List

如果你還沒有實現EqualsGetHashCode你必須發明分組鍵,例如:

 studentsList = studentsList
   .GroupBy(o => new { // Student are equal if and only if they have same
      o.Student.Name,  // Name 
      o.Student.Age,   // and Age
    }) 
   .Where(group => group.Count() >= 2) 
   .SelectMany(group => group)
   .ToList();

在這種情況下,我建議您使用HashSet

請記住始終嘗試將您的數據結構與您要解決的問題相匹配。 考慮一下,你會嘗試用錘子在牆上釘一個螺絲嗎? 當然,這是可能的,但不是最優的。

如果你很難堅持使用 LINQ 和 Lists 來解決這個問題,你可以在你的列表上調用 .Distinct() ,它會返回不同的元素。

首先取所有至少出現兩次的值:

var atLeastTwicePresent = studentsList
    .Select(sObj => sObj.Student)
    .Where(s => studentsList.Where(sObj => sObj.Student == s).Count() > 1);

然后從這個集合中獲取不同的值:

var distinctAtLeastTwice = atLeastTwicePresent.Distinct().ToList();

並且您的列表中應該有至少出現兩次的 Distinct Student 姓名。

如果您只想讓結果中至少出現兩次的學生,請嘗試將它們分組並根據計數過濾組:

studentsList.GroupBy(s => s.Student).Where(g => g.Count() > 1).Select(g => g.First())

或者

from s in studentsList
group s by s.Student into g
where g.Count() > 1
select g.First()

您需要按所需的鍵對項目進行分組。 使用new { } ,您可以使用 linq 組創建密鑰。 然后,不要選擇組中的第一個密鑰(這是一個匿名的 class,您不想要) ,而是選擇 select。

匿名 class 的想法是,組比較所有屬性,所以它可以是組。 (這就是為什么你不能在 MyStudents 課上分組)

你可以試試這個:

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

public class MyStudents
{
     private string student;
     private int age;

     public string Student
     {
         get { return student; }
         set { student = value; }
     }

     public int Age
     {
         get { return age; }
         set { age = value; }
     }
}

public class Program
{
    public static void Main()
    {
        // some testdata...
        var students = new List<MyStudents>
        {
            new MyStudents { Student = "John", Age = 17 },
            new MyStudents { Student = "Mary", Age = 18 },
            new MyStudents { Student = "John", Age = 17 },
            new MyStudents { Student = "Hank", Age = 20 },
        };


        var newList = students

           // The whole idea is, group the list by creating a key.
           .GroupBy(o => new {o.Student, o.Age})
           // you don't want to select the key, because it's an anonymous class
           // So select the first item which was added to the group.
           .Select(o => o.First())
           // create a new list.
           .ToList();

        // present them         
        foreach(var s in newList)
            Console.WriteLine("Student: "+s.Student+", Age: "+s.Age);
    }
}}

這是一個dotnetfiddle

這是一個示例:使用 list.Distinct().ToList();

// List with duplicate elements.
        List<int> list = new List<int>();
        list.Add(1);
        list.Add(2);
        list.Add(3);
        list.Add(3);
        list.Add(4);
        list.Add(4);
        list.Add(4);

        foreach (int value in list)
        {
            Console.WriteLine("Before: {0}", value);
        }

        // Get distinct elements and convert into a list again.
        List<int> distinct = list.Distinct().ToList();

        foreach (int value in distinct)
        {
            Console.WriteLine("After: {0}", value);
        }
    }

dotnetfiddle


對類使用.destinct 需要比較器方法:請參見此處。 但它必須是 IEqualityComparer 的一個實例!

class ProductComparer : IEqualityComparer<Product>  
{
            public bool Equals(Product x, Product y) {
                if (Object.ReferenceEquals(x, y)) return true;

                if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                    return false;

                return x.Make == y.Make && x.Model == y.Model;
            }
            public int GetHashCode(Product product) {
                if (Object.ReferenceEquals(product, null)) return 0;
                int hashProductName = product.Make == null ? 0 : product.Make.GetHashCode();
                int hashProductCode = product.Model.GetHashCode();
                return hashProductName ^ hashProductCode;
            }
 }

**The Distinct operator has an overload method that lets you pass an instance of IEqualityComparer.** So for this approach we created a class “ProductComparer” that implements the IEqualityCompaper. Here’s the code to use it:


if (!IsPostBack) {  
                GridView1.DataSource = GetProducts()
                                       .Distinct(new ProductComparer());
                GridView1.DataBind();
}

如果您想獲得所有獨特的 Student,那么您只需要將 select 與您的列表不同。

像這樣:studentList.DistinctBy(x => x.id);

暫無
暫無

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

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