(C#) 設定作業

LINQ 中的設定作業指的是產生結果集的查詢作業,而結果集是根據相同或不同集合 (集) 內是否有對等項目而定。

下節列出執行設定作業的標準查詢運算子方法。

方法

方法名稱 描述 C# 查詢運算式語法 詳細資訊
Distinct 或 DistinctBy 移除集合中的重複值。 不適用。 Enumerable.Distinct
Enumerable.DistinctBy
Queryable.Distinct
Queryable.DistinctBy
Except 或 ExceptBy 傳回集差異,表示未出現在第二個集合中的某個集合中的項目。 不適用。 Enumerable.Except
Enumerable.ExceptBy
Queryable.Except
Queryable.ExceptBy
Intersect 或 IntersectBy 傳回集交集,表示出現在這兩個集合中的項目。 不適用。 Enumerable.Intersect
Enumerable.IntersectBy
Queryable.Intersect
Queryable.IntersectBy
Union 或 UnionBy 傳回集聯集,表示出現在兩個集合中任一集合的唯一項目。 不適用。 Enumerable.Union
Enumerable.UnionBy
Queryable.Union
Queryable.UnionBy

範例

下列部分範例依賴一種 record 類型來代表我們的太陽能系統中的行星。

namespace SolarSystem;

record Planet(
    string Name,
    PlanetType Type,
    int OrderFromSun)
{
    public static readonly Planet Mercury =
        new(nameof(Mercury), PlanetType.Rock, 1);

    public static readonly Planet Venus =
        new(nameof(Venus), PlanetType.Rock, 2);

    public static readonly Planet Earth =
        new(nameof(Earth), PlanetType.Rock, 3);

    public static readonly Planet Mars =
        new(nameof(Mars), PlanetType.Rock, 4);

    public static readonly Planet Jupiter =
        new(nameof(Jupiter), PlanetType.Gas, 5);

    public static readonly Planet Saturn =
        new(nameof(Saturn), PlanetType.Gas, 6);

    public static readonly Planet Uranus =
        new(nameof(Uranus), PlanetType.Liquid, 7);

    public static readonly Planet Neptune =
        new(nameof(Neptune), PlanetType.Liquid, 8);

    // Yes, I know... not technically a planet anymore
    public static readonly Planet Pluto =
        new(nameof(Pluto), PlanetType.Ice, 9);
}

record Planet是位置記錄,需要 NameTypeOrderFromSun 引數來具現化它。 類型上有 Planetstatic readonly 個行星實例。 這些是已知行星的便利型定義。 成員 Type 會識別行星類型。

namespace SolarSystem;

enum PlanetType
{
    Rock,
    Ice,
    Gas,
    Liquid
};

DistinctDistinctBy

下列範例描述方法在字串序列上的行為 Enumerable.Distinct 。 所傳回的序列包含輸入序列中的唯一項目。

Graphic showing the behavior of Distinct().

string[] planets = { "Mercury", "Venus", "Venus", "Earth", "Mars", "Earth" };

IEnumerable<string> query = from planet in planets.Distinct()
                            select planet;

foreach (var str in query)
{
    Console.WriteLine(str);
}

/* This code produces the following output:
 *
 * Mercury
 * Venus
 * Earth
 * Mars
 */

DistinctBy是採用 的 DistinctkeySelector 替代方法。 keySelector會作為來源類型的比較鑒別子。 請考慮下列行星陣列:

Planet[] planets =
{
    Planet.Mercury,
    Planet.Venus,
    Planet.Earth,
    Planet.Mars,
    Planet.Jupiter,
    Planet.Saturn,
    Planet.Uranus,
    Planet.Neptune,
    Planet.Pluto
};

在下列程式碼中,行星會根據其 PlanetType 區分,而且會顯示每個類型的第一個行星:

foreach (Planet planet in planets.DistinctBy(p => p.Type))
{
    Console.WriteLine(planet);
}

// This code produces the following output:
//     Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
//     Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
//     Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
//     Planet { Name = Pluto, Type = Ice, OrderFromSun = 9 }

在上述 C# 程式碼中:

  • 陣列 Planet 會根據每個唯一行星類型的第一個出現專案,以不同的方式進行篩選。
  • 產生的 planet 實例會寫入主控台。

ExceptExceptBy

下列範例描述 的行為 Enumerable.Except 。 所傳回的序列只包含第一個輸入序列中不在第二個輸入序列中的項目。

Graphic showing the action of Except().

string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" };
string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" };

IEnumerable<string> query = from planet in planets1.Except(planets2)
                            select planet;

foreach (var str in query)
{
    Console.WriteLine(str);
}

/* This code produces the following output:
 *
 * Venus
 */

方法 ExceptBy 是替代方法 Except ,採用兩個可能異質型別和 keySelector 的序列。 keySelector與第二個集合的類型相同,而且會當做來源類型的比較鑒別子使用。 請考慮下列行星陣列:

Planet[] planets =
{
    Planet.Mercury,
    Planet.Venus,
    Planet.Earth,
    Planet.Jupiter
};

Planet[] morePlanets =
{
    Planet.Mercury,
    Planet.Earth,
    Planet.Mars,
    Planet.Jupiter
};

若要在第一個集合中尋找不在第二個集合中的行星,您可以將行星名稱投影為 second 集合,並提供相同的 keySelector

// A shared "keySelector"
static string PlanetNameSelector(Planet planet) => planet.Name;

foreach (Planet planet in
    planets.ExceptBy(
        morePlanets.Select(PlanetNameSelector), PlanetNameSelector))
{
    Console.WriteLine(planet);
}

// This code produces the following output:
//     Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }

在上述 C# 程式碼中:

  • keySelector定義為 static 區分行星名稱的區域函式。
  • 第一個行星陣列會根據其名稱篩選為在第二個行星陣列中找不到的行星。
  • 產生的 planet 實例會寫入主控台。

IntersectIntersectBy

下列範例描述 的行為 Enumerable.Intersect 。 所傳回的序列包含兩個輸入序列共有的項目。

Graphic showing the intersection of two sequences.

string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" };
string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" };

IEnumerable<string> query = from planet in planets1.Intersect(planets2)
                            select planet;

foreach (var str in query)
{
    Console.WriteLine(str);
}

/* This code produces the following output:
 *
 * Mercury
 * Earth
 * Jupiter
 */

方法 IntersectBy 是替代方法 Intersect ,採用兩個可能異質型別和 keySelector 的序列。 keySelector用來做為第二個集合類型的比較鑒別子。 請考慮下列行星陣列:

Planet[] firstFivePlanetsFromTheSun =
{
    Planet.Mercury,
    Planet.Venus,
    Planet.Earth,
    Planet.Mars,
    Planet.Jupiter
};

Planet[] lastFivePlanetsFromTheSun =
{
    Planet.Mars,
    Planet.Jupiter,
    Planet.Saturn,
    Planet.Uranus,
    Planet.Neptune
};

行星有兩個數組;其中一個代表來自太陽的前五個行星,而第二個則代表來自太陽的最後五個行星。 Planet因為類型是位置 record 類型,所以您可以使用其值比較語意,格式為 keySelector

foreach (Planet planet in
    firstFivePlanetsFromTheSun.IntersectBy(
        lastFivePlanetsFromTheSun, planet => planet))
{
    Console.WriteLine(planet);
}

// This code produces the following output:
//     Planet { Name = Mars, Type = Rock, OrderFromSun = 4 }
//     Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }

在上述 C# 程式碼中:

  • 這兩 Planet 個數組會與其值比較語意交集。
  • 只有在這兩個數組中找到的行星才會出現在產生的序列中。
  • 產生的 planet 實例會寫入主控台。

UnionUnionBy

下列範例描述兩個字串序列的聯集運算。 所傳回的序列包含兩個輸入序列中的唯一項目。

Graphic showing the union of two sequences.

string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" };
string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" };

IEnumerable<string> query = from planet in planets1.Union(planets2)
                            select planet;

foreach (var str in query)
{
    Console.WriteLine(str);
}

/* This code produces the following output:
 *
 * Mercury
 * Venus
 * Earth
 * Jupiter
 * Mars
 */

方法是 UnionBy 採用相同型別和 keySelector 的兩個序列的 Union 替代方法。 keySelector會作為來源類型的比較鑒別子。 請考慮下列行星陣列:

Planet[] firstFivePlanetsFromTheSun =
{
    Planet.Mercury,
    Planet.Venus,
    Planet.Earth,
    Planet.Mars,
    Planet.Jupiter
};

Planet[] lastFivePlanetsFromTheSun =
{
    Planet.Mars,
    Planet.Jupiter,
    Planet.Saturn,
    Planet.Uranus,
    Planet.Neptune
};

若要將這兩個集合聯集成單一序列,請提供 keySelector

foreach (Planet planet in
    firstFivePlanetsFromTheSun.UnionBy(
        lastFivePlanetsFromTheSun, planet => planet))
{
    Console.WriteLine(planet);
}

// This code produces the following output:
//     Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
//     Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }
//     Planet { Name = Earth, Type = Rock, OrderFromSun = 3 }
//     Planet { Name = Mars, Type = Rock, OrderFromSun = 4 }
//     Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
//     Planet { Name = Saturn, Type = Gas, OrderFromSun = 6 }
//     Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
//     Planet { Name = Neptune, Type = Liquid, OrderFromSun = 8 }

在上述 C# 程式碼中:

  • 這兩 Planet 個數組會使用其值比較語意,將兩 record 個數組交集在一起。
  • 產生的 planet 實例會寫入主控台。

另請參閱