簡體   English   中英

為什么 Union() 沒有像它應該的那樣排除重復項?

[英]Why is Union() not excluding duplicates like it should?

編輯:為什么 Union() 沒有像它應該的那樣排除重復項?

在提出原始問題之前,我應該閱讀文檔。 我沒有,因為每次我使用 Union() 時都是在沒有覆蓋 Equals() 和 GetHashCode() 的對象列表上,所以即使列表中每個對象的字段值相同,它們將在創建的新列表 Union() 內。 起初,似乎 Union() 沒有排除重復項,而我認為這是真的。 但實際上, Union() 確實排除了重復項。 不僅在兩個列表中重復,而且在同一個列表中也重復。 如果我的對象不覆蓋 Equals() 和 GetHashCode() 它們不會按值進行比較,這意味着它們看起來不是重復的。

這是讓我問這個問題的困惑。

一旦我使用 Union() 和 Select() 顯式地創建了一個新列表,“T”將成為一個匿名類型,按值進行比較。 這樣,具有相同字段值的對象將被視為重復。 to behave differently).這就是導致 Union() 表現不同(或者表現不同)的原因。 它總是排除重復項,但並不總是按值比較類型,因此具有相同字段值的對象可能會或可能不會看起來是重復的。 這取決於您的自定義類的實現。

我想這應該是一個問題:為什么 Union() 沒有像它應該的那樣排除重復項? (正如我們所見,這是因為我的對象並不是真正的重復項)。 那正確嗎?

---------------

原始問題: LINQ Union + Select 會自動刪除重復項。 為什么?

我一直認為 Linq 中的 Union() 會返回兩個列表中的所有值,即使它們相同。 但是當我在 Union() 之后使用“Select()”時,我的代碼正在從第一個列表中刪除重復項。

想象一下球提取的經典概率問題,我有不同的容器,我從容器中提取一些不同的球。

我有兩個 BallExtraction 列表。 每個列表都顯示了球的 ID、球所在容器的 ID、我提取的球數(值)及其顏色。 但是,出於某種原因,我有兩個不同的列表,我想合並它們。

示例代碼:

class BallExtraction
{
    public enum BallColor 
    {
        Blue = 0,
        Red = 1
    } 

    public int Id { get; set; }
    public int IdContainer { get; set; }
    public int ValueExtracted { get; set; }
    public BallColor Color { get; set; }

    public BallExtraction() { }

    public BallExtraction(int id, int idContainer, int valueExtracted, BallColor color)
    {
        this.Id = id;
        this.IdContainer = idContainer;
        this.ValueExtracted = valueExtracted;
        this.Color = color;
    }

}

現在我運行以下程序:

class Program
{
    static void Main(string[] args)
    {
        List<BallExtraction> list1 = new List<BallExtraction>();
        list1.Add(new BallExtraction(1, 1, 20, BallExtraction.BallColor.Blue));
        list1.Add(new BallExtraction(1, 1, 20, BallExtraction.BallColor.Blue));
        list1.Add(new BallExtraction(1, 1, 20, BallExtraction.BallColor.Red));
        list1.Add(new BallExtraction(1, 2, 70, BallExtraction.BallColor.Blue));
        list1.Add(new BallExtraction(2, 1, 10, BallExtraction.BallColor.Blue));

        List<BallExtraction> list2 = new List<BallExtraction>();
        list1.Add(new BallExtraction(3, 2, 80, BallExtraction.BallColor.Blue));
        list1.Add(new BallExtraction(3, 2, 80, BallExtraction.BallColor.Red));

        var mergedList = list1.Where(w => w.Color == BallExtraction.BallColor.Blue).Select(s => new
        {
            Id = s.Id,
            IdContainer = s.IdContainer,
            ValueExtracted = s.ValueExtracted
        }).Union(list2.Where(w => w.Color == BallExtraction.BallColor.Blue).Select(s => new
        {
            Id = s.Id,
            IdContainer = s.IdContainer,
            ValueExtracted = s.ValueExtracted
        }));

        Console.WriteLine("Number of items: {0}", mergedList.Count());

        foreach (var item in mergedList)
        {
            Console.WriteLine("Id: {0}. IdContainer: {1}. # of balls extracted: {2}", item.Id, item.IdContainer, item.ValueExtracted);
        }

        Console.ReadLine();

    }
}

預期的輸出是:

Number of items: 5
Id: 1. IdContainer: 1. Value: 20.
Id: 1. IdContainer: 1. Value: 20.
Id: 1. IdContainer: 2. Value: 70.
Id: 2. IdContainer: 1. Value: 10.
Id: 3. IdContainer: 2. Value: 80.    

但實際輸出是:

Number of items: 4
Id: 1. IdContainer: 1. Value: 20.
Id: 1. IdContainer: 2. Value: 70.
Id: 2. IdContainer: 1. Value: 10.
Id: 3. IdContainer: 2. Value: 80.

請注意,第一個列表包含兩個具有相同值的提取。 球的Id為1,容器的Id為1,提取的球數為20,均為藍色。

我發現當我將 'mergedList' 切換到下面的代碼時,我得到了預期的輸出:

var mergedList = list1.Where(w => w.Color == BallExtraction.BallColor.Blue).Union(list2.Where(w => w.Color == BallExtraction.BallColor.Blue));

因此,似乎在 Union() 之后使用的“選擇”正在從第一個列表中刪除重復項。

真正的問題是,我實際上沒有像示例中那樣的簡單類型列表,但我有一個 IEnumerable< T > 列表(T 是匿名類型)並且 T 有很多字段。 我只想要特定的字段,但我想要所有新的匿名類型重復項。 我發現的唯一解決方法是,如果在 'Select()' 中添加一些對每個對象 T 都是唯一的字段。

這是否按預期工作? Union + Select 應該刪除重復項嗎?

是的,這是預期的行為。

聯盟的文件狀態

返回值 類型:System.Collections.Generic.IEnumerable 一個 IEnumerable,包含來自兩個輸入序列的元素,不包括重復項

要保留重復項,您必須使用Concat() ,而不是Union()

暫無
暫無

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

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