使用LINQ的外部联接

本文关键字:外部 LINQ 使用 | 更新日期: 2023-09-27 17:59:43

我有两个列表。我的列表如下:

可用风味

ID  Name
--  ----
1   Vanilla
2   Chocolate
3   Strawberry
4   Rocky Road
5   Cookies and Cream

FavoriteFlavors

ID  Name
--  ----
1   Vanilla
3   Strawberry

如何使用LINQ获取不在FavoriteFlavors列表中的AvailableFlavors列表?目前我有:

List<Flavor> AvailableFlavors = GetAvailableFlavors();
List<Flavor> FavoriteFlavors = GetFavoriteFlavors();
AvailableFlavors = from availableFlavor in AvailableFlavors
                   // what goes here?
                   select availableFlavor;

使用LINQ的外部联接

简单的LINQ .Except调用就能完成任务:

List<Flavor> AvailableFlavors = GetAvailableFlavors();
List<Flavor> FavoriteFlavors = GetFavoriteFlavors();
var availableButNotFavoriteFlavors = AvailableFloavors.Except(FavoriteFlaovors);

结果是IEnumerable<Flavor>,因此您可能需要转换回List。

编辑:我想真正的问题是如何编写我们在`中使用的自定义IEqualityComparer。Except方法。这除了文档页面有一个写简单比较器的好例子。

如果你不介意这样做,另一种选择就是使用.Where并手动比较属性:

var availableButNotFavoriteFlavors =
    AvailableFloavors
        .Where(af => !FavoriteFlavors.Any(ff => af.Id == ff.ID && af.Name == ff.Name);

使用自定义类Flavor,我重写Equals()ToString(),并执行以下操作:

using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
    public static void Main()
    {
        List<Flavor> availableFlavors = new List<Flavor> () {
            new Flavor() { ID = 1, Name = "Vanilla" },
            new Flavor() { ID = 2, Name = "Chocolate" },
            new Flavor() { ID = 3, Name = "Strawberry" },
            new Flavor() { ID = 4, Name = "Rocky Road" },
            new Flavor() { ID = 5, Name = "Cookies and Cream"}
        };
        List<Flavor> favoriteFlavors = new List<Flavor>() {
            new Flavor() { ID = 1, Name = "Vanilla" },
            new Flavor() { ID = 3, Name = "Strawberry" },
        };
        availableFlavors.Where(f => !favoriteFlavors.Contains(f))
            .ToList()
            .ForEach(f => Console.WriteLine(f));
    }
}
public class Flavor
{
    public int ID { get; set; }
    public string Name { get; set; }
    public override bool Equals(object obj)
    {
        Flavor objToCheck = obj as Flavor;
        if (objToCheck != null)
        {
            if (objToCheck.ID == ID &&
                objToCheck.Name == Name)
            {
                return true;
            }
            return false;
        }
        return false;
    }
    public override string ToString()
    {
        return String.Format("ID: {0} Name: {1}", ID, Name);
    }
}

结果:

ID: 2 Name: Chocolate
ID: 4 Name: Rocky Road
ID: 5 Name: Cookies and Cream

演示

// Select Name from favorite flavors
var favoriteFlavorNames = from favoriteFlavor in GetFavoriteFlavors()
                          select favoriteFlavor.Name;
// Find available flavors not in favorite flavors
var filteredAvailbleFlavors = from availableFlavor in GetAvailableFlavors()
                              where !favoriteFlavorNames.Contains(availableFlavor.Name)
                              select availableFlavor;

或者您可以将两者合并为:

var filteredAvailbleFlavors = from availableFlavor in GetAvailableFlavors()
                              let favoriteFlavorNames = 
                                  (from favoriteFlavor in GetFavoriteFlavors()
                                   select favoriteFlavor.Name)
                              where !favoriteFlavorNames.Contains(availableFlavor.Name)
                              select availableFlavor;
AvailableFlavors.Where(af => !FavoriteFlavors.Any(ff => af.Name == ff.Name));