怎么用自己的网站做链轮/seo网站推广技术

怎么用自己的网站做链轮,seo网站推广技术,订阅号可以做网站么,北京网站建设方案案例总目录 前言 在 C# 中,System.Linq.Enumerable 类是 LINQ(Language Integrated Query)的核心组成部分,它提供了一系列静态方法,用于操作实现了 IEnumerable 接口的集合。通过这些方法,我们可以轻松地对集合…

总目录


前言

在 C# 中,System.Linq.Enumerable 类是 LINQ(Language Integrated Query)的核心组成部分,它提供了一系列静态方法,用于操作实现了 IEnumerable 接口的集合。通过这些方法,我们可以轻松地对集合进行查询、转换、排序和聚合等操作。

本文属于 C# Enumerable类 使用详解 中的一个章节,着重介绍 C# Enumerable 类中集合操作这部分的内容。


一、概览

方法描述示例
Concat序列合并(不去重)list1.Concat(list2);
UnionUnionBy序列并集(去重)list1.Union(list2);
ExceptExceptBy 序列差集list1.Except(list2);
IntersectIntersectBy 序列交集list1.Intersect(list2);

二、Concat :合并(不去重)

1. 什么是 Concat

Concat 是 LINQ 提供的一个扩展方法,用于将两个序列连接在一起,并返回一个包含所有元素的新序列。需要注意的是,Concat 方法不会去除重复项,如果需要去重可以使用 Union 方法。

2. Concat 方法 基本信息

1) Concat

public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first,IEnumerable<TSource> second)
  • 参数
    • first:第一个要连接的序列。
    • second:第二个要连接的序列。
  • 返回值Concat 方法返回一个 IEnumerable<T> 对象,其中 T 是输入序列中元素的类型。

2)工作原理

Concat 方法通过惰性求值和迭代器模式,将两个序列依次遍历并返回一个新的序列,过程中不会创建新的集合对象,而是逐个返回两个序列中的元素。

3)使用场景

适用于合并多个集合、处理流式数据、数据预处理等场景。

3. 使用示例

示例 1:基本连接

假设我们有两个整数列表,我们希望将它们连接在一起形成一个新的列表。

class Program
{static void Main(){List<int> list1 = new List<int> { 1, 2, 3 };List<int> list2 = new List<int> { 4, 5, 6 };// 使用 Concat 连接两个列表var concatenatedList = list1.Concat(list2);Console.WriteLine(string.Join(",",concatenatedList));// 输出:1,2,3,4,5,6}
}

示例 2:不同类型的序列

虽然 Concat 方法要求两个序列的元素类型相同,但可以通过泛型和隐式转换来处理不同类型的数据。

class Program
{static void Main(){List<string> list1 = new List<string> { "Apple", "Banana" };List<object> list2 = new List<object> { 1, 2.5, true };// 使用 Concat 连接两个不同类型的列表var concatenatedList = list1.Cast<object>().Concat(list2);Console.WriteLine(string.Join(",",concatenatedList));// 输出:Apple,Banana,1,2.5,True}
}

示例 3:空序列

Concat 方法也可以用于将一个非空序列与一个空序列连接。

class Program
{static void Main(){List<int> list1 = new List<int> { 1, 2, 3 };List<int> list2 = new List<int>();// 使用 Concat 连接非空序列和空序列var concatenatedList = list1.Concat(list2);Console.WriteLine(string.Join(",",concatenatedList));// 输出:1,2,3}
}

示例 4:合并多个集合

当需要合并多个集合时,可以多次使用 Concat 方法,或者使用 Union 方法来去除重复项。

class Program
{static void Main(){List<int> list1 = new List<int> { 1, 2, 3 };List<int> list2 = new List<int> { 3, 4, 5, 6 };List<int> list3 = new List<int> { 6, 7, 8, 9 };// 使用 Concat 合并多个集合var concatenatedList = list1.Concat(list2).Concat(list3);Console.WriteLine(string.Join(",", concatenatedList));// 输出:1,2,3,3,4,5,6,6,7,8,9// 使用 Union 去除重复项var unionedList = list1.Union(list2).Union(list3);Console.WriteLine(string.Join(",", unionedList));// 输出:1,2,3,4,5,6,7,8,9}
}

示例 5:处理流式数据

由于 Concat 方法采用惰性求值,因此非常适合处理流式数据或无限序列。

class Program
{static void Main(){IEnumerable<int> streamData = GenerateStreamData();List<int> additionalData = new List<int> { 10, 20, 30 };// 使用 Concat 连接流式数据和附加数据var concatenatedStream = streamData.Concat(additionalData);// 输出结果Console.WriteLine("Concatenated Stream Data (First 10 elements):");foreach (var item in concatenatedStream.Take(10)){Console.Write(item + " ");}}static IEnumerable<int> GenerateStreamData(){int i = 0;while (true){yield return i++;}}
}

输出结果:

Concatenated Stream Data (First 10 elements):
0 1 2 3 4 5 6 7 8 9

示例 6:数据预处理

在某些情况下,你可能需要对数据进行预处理,然后再将其与其他数据连接起来。

using System;
using System.Collections.Generic;
using System.Linq;class Program
{static void Main(){List<int> rawData = new List<int> { 1, 2, 3, 4, 5 };List<int> processedData = rawData.Select(x => x * 2).ToList();List<int> additionalData = new List<int> { 10, 20, 30 };// 使用 Concat 连接预处理后的数据和其他数据var concatenatedData = processedData.Concat(additionalData);// 输出结果Console.WriteLine("Concatenated Data:");foreach (var item in concatenatedData){Console.Write(item + " ");}}
}

输出结果:

Concatenated Data:
2 4 6 8 10 10 20 30

4. 注意事项

尽管 Concat 方法非常有用,但在实际应用中也有一些需要注意的地方:

  • 空集合处理: 如果源集合为空,Concat 方法将返回一个空的结果集。因此,在使用 Concat 方法之前,通常不需要检查集合是否为空。
  • 数据类型一致:适用于需要合并的集合对象的数据类型是一样的情况。

三、UnionUnionBy:并集(去重)

在这里插入图片描述

1. 什么是 Union/UnionBy

  • Union 是 LINQ 提供的一个扩展方法,用于将两个序列合并成一个新的序列,并去除重复的元素。这个方法非常有用,特别是在需要合并多个集合并确保结果中没有重复项时。
  • UnionBy 是 .NET 6 及以上版本中引入的一个扩展方法,用于合并两个序列并根据指定的键选择器函数去除重复项。与 Union 方法不同的是,UnionBy 允许你通过一个自定义的键来确定元素是否相同,而不是直接比较整个对象。

2. Union/UnionBy 方法 基本信息

1) Union/UnionBy

public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first,IEnumerable<TSource> second
)public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first,IEnumerable<TSource> second,IEqualityComparer<TSource> comparer
)
  • 参数
    • first:第一个要合并的序列。
    • second:第二个要合并的序列。
    • comparer(可选):一个 IEqualityComparer<TSource> 实现,用于比较元素是否相等。
  • 返回值Union 方法返回一个 IEnumerable<T> 对象,其中 T 是输入序列中元素的类型。
public static IEnumerable<TSource> UnionBy<TSource, TKey>(this IEnumerable<TSource> first,IEnumerable<TSource> second,Func<TSource, TKey> keySelector
)public static IEnumerable<TSource> UnionBy<TSource, TKey>(this IEnumerable<TSource> first,IEnumerable<TSource> second,Func<TSource, TKey> keySelector,IEqualityComparer<TKey> comparer
)
  • 参数
    • first:第一个要合并的序列。
    • second:第二个要合并的序列。
    • keySelector:一个函数,用于从每个元素中提取键值。
    • comparer(可选):一个 IEqualityComparer 实现,用于比较键值是否相等。
  • 返回值UnionBy 方法返回一个 IEnumerable<TSource> 对象,其中 TSource 是输入序列中元素的类型。

2)工作原理

  • Union 方法通过惰性求值和迭代器模式,将两个序列合并成一个新的序列,并在遍历过程中自动去除重复元素。
  • UnionBy 方法通过指定的键选择器函数从两个序列中提取键值,并根据这些键值合并序列,去除重复项,最终返回一个包含唯一键值元素的新序列。

3)使用场景

适用于合并多个集合、处理流式数据、数据预处理、复杂数据结构合并等场景。

3. 使用示例

示例 1:基本合并

假设我们有两个整数列表,我们希望将它们合并在一起形成一个新的列表,并去除重复项。

class Program
{static void Main(){List<int> list1 = new List<int> { 1, 2, 3 };List<int> list2 = new List<int> { 3, 4, 5 };// 使用 Union 合并两个列表并去除重复项var unionedList = list1.Union(list2);Console.WriteLine(string.Join(",", unionedList));// 输出:1,2,3,4,5// 使用 UnionBy 合并两个列表并去除重复项unionedList = list1.UnionBy(list2, x => x);Console.WriteLine(string.Join(",", unionedList));// 输出:1,2,3,4,5}
}

在这个例子中,我们使用 Union / UnionBy 方法将两个整数列表合并在一起,并打印了结果。注意,数字 3 只出现了一次。

示例 2:自定义对象

当处理自定义对象时,Union 方法默认使用对象的 EqualsGetHashCode 方法来判断元素是否相同。如果你有更复杂的比较需求,可以提供自定义的 IEqualityComparer<T> 实现。

  • 使用默认的 EqualsGetHashCode 方法,并不能实现对象内容的比较
class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}
class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "Bob", Age = 25 }};// 使用 Union 合并两个列表并去除重复项var unionedPeople = list1.Union(list2);Console.WriteLine(string.Join(",",unionedPeople));// 输出:Alice (30),Bob (25),Charlie (30),Bob (25)}
}
  • 重写 对象的 EqualsGetHashCode 方法,可以实现对象内容的比较。使用Union时,默认就会调用重写后的方法判断对象是否相等
class Person
{public string Name { get; set; }public int Age { get; set; }public override bool Equals(object obj){if (obj is Person other){return Name == other.Name && Age == other.Age;}return false;}public override int GetHashCode(){return HashCode.Combine(Name, Age);}public override string ToString(){return $"{Name} ({Age})";}
}
class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "Bob", Age = 25 }};// 使用 Union 合并两个列表并去除重复项var unionedPeople = list1.Union(list2);Console.WriteLine(string.Join(",",unionedPeople));// 输出:Alice (30),Bob (25),Charlie (30)}
}
  • 使用自定义的 PersonComparer 来比较 Person 对象,并确保合并后的结果中没有重复项。
class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}
class PersonComparer : IEqualityComparer<Person>
{public bool Equals(Person x, Person y){if (x == null || y == null) return false;return x.Name == y.Name && x.Age == y.Age;}public int GetHashCode(Person obj){return HashCode.Combine(obj.Name, obj.Age);}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{`在这里插入代码片`new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "Bob", Age = 25 }};// 使用 Union 合并两个列表并去除重复项var unionedPeople = list1.Union(list2,new PersonComparer());Console.WriteLine(string.Join(",",unionedPeople));// 输出:Alice (30),Bob (25),Charlie (30)}
}
  • 使用UnionBy ,通过指定键选择器函数来确定哪些对象应该被视为相同的。并确保合并后的结果中没有重复项。
class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "Bob", Age = 25 }};// 使用 UnionBy 合并两个列表并根据年龄去重var unionedPeople = list1.UnionBy(list2, p => p.Age);Console.WriteLine(string.Join(",", unionedPeople));// 输出:Alice (30),Bob (25)}
}

示例 3:处理无限序列

Union /UnionBy方法采用惰性求值(Lazy Evaluation),这意味着它不会立即执行合并操作,而是等到实际遍历时才会计算结果。这使得 Union /UnionBy 可以处理无限序列或延迟执行复杂的查询。

using System;
using System.Collections.Generic;
using System.Linq;class Program
{static void Main(){IEnumerable<int> infiniteNumbers = Enumerable.Range(0, int.MaxValue).Select(i => i * 2);List<int> finiteNumbers = new List<int> { 1, 3, 5 };// 使用 Union 合并无限序列和有限序列var unionedSequence = infiniteNumbers.Union(finiteNumbers);// var unionedSequence = infiniteNumbers.UnionBy(finiteNumbers, x => x);// 限制输出数量Console.WriteLine("Unioned Sequence (First 10 elements):");foreach (var item in unionedSequence.Take(10)){Console.Write(item + " ");}}
}

输出结果:

Unioned Sequence (First 10 elements):
0 2 4 6 8 10 12 14 16 18

在这个例子中,我们展示了如何使用 Union /UnionBy 方法合并一个无限序列和一个有限序列,并通过 Take 方法限制输出的数量,从而避免无限循环。

示例 4:自定义比较器

当处理复杂的数据结构时,可以通过自定义比较器来实现更灵活的合并逻辑。

class Person
{public string Name { get; set; }public int Age { get; set; }public override bool Equals(object obj){if (obj is Person other){return Name == other.Name && Age == other.Age;}return false;}public override int GetHashCode(){return HashCode.Combine(Name, Age);}public override string ToString(){return $"{Name} ({Age})";}
}class PersonComparerByName : IEqualityComparer<Person>
{public bool Equals(Person x, Person y){if (x == null || y == null) return false;return x.Name == y.Name;}public int GetHashCode(Person obj){return obj.Name?.GetHashCode() ?? 0;}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Alice", Age = 31 },new Person { Name = "Charlie", Age = 30 }};// 使用 Union 合并两个列表并根据名字去重var unionedPeople = list1.Union(list2, new PersonComparerByName());Console.WriteLine(string.Join(",", unionedPeople));// 输出:Alice (30),Bob (25),Charlie (30)}
}

在这个例子中,我们展示了如何使用自定义的 PersonComparerByName 来根据名字去重合并 Person 对象。

class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}class CustomAgeComparer : IEqualityComparer<int>
{public bool Equals(int x, int y){// 自定义比较逻辑:年龄相差不超过1岁视为相同return Math.Abs(x - y) <= 1;}public int GetHashCode(int obj){return 0;}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "David", Age = 26 }};// 使用 UnionBy 合并两个列表并根据年龄和自定义比较器去重var unionedPeople = list1.UnionBy(list2, p => p.Age, new CustomAgeComparer());Console.WriteLine(string.Join(",", unionedPeople));// 输出:Alice (30),Bob (25)}
}

示例 5:多个集合的合并

当需要合并多个集合时,可以多次使用 Union 方法。

class Program
{static void Main(){List<int> list1 = new List<int> { 1, 2, 3 };List<int> list2 = new List<int> { 4, 5, 6 };List<int> list3 = new List<int> { 7, 8, 9 };// 使用 Union 合并多个集合var unionedLists = list1.Union(list2).Union(list3);// var unionedLists = list1.UnionBy(list2, x => x).UnionBy(list3, x => x);Console.WriteLine(string.Join(",", unionedLists));// 输出:1,2,3,4,5,6,7,8,9}
}

4. 注意事项

尽管 Union/UnionBy 方法非常有用,但在实际应用中也有一些需要注意的地方:

  • 空集合处理: 如果源集合为空,Union/UnionBy 方法将返回一个空的结果集。因此,在使用 Union /UnionBy方法之前,通常不需要检查集合是否为空。
  • 数据类型一致:适用于需要合并的集合对象的数据类型是一样的情况。

四、ExceptExceptBy :差集

在这里插入图片描述

1. 什么是 Except/ExceptBy

  • Except 方法用于计算两个序列的差集,即返回第一个序列中存在但第二个序列中不存在的所有元素。默认情况下,它使用对象的默认比较器(如 EqualityComparer.Default)来比较元素是否相等。你也可以提供自定义的比较器来控制比较逻辑。
  • ExceptBy 是 .NET 6 及以上版本中引入的一个扩展方法,用于计算两个序列的差集,但与 Except 不同的是,它允许你通过指定的键选择器函数来确定元素是否相同。这意味着你可以根据某个特定属性或计算结果来进行差集操作,而不是直接比较整个对象。

2. Except/ExceptBy 方法 基本信息

1) Except/ExceptBy

public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first,IEnumerable<TSource> second
)public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first,IEnumerable<TSource> second,IEqualityComparer<TSource> comparer
)
  • 参数
    • first:第一个要计算差集的序列。
    • second:第二个要计算差集的序列。
    • comparer(可选):一个 IEqualityComparer<TSource> 实现,用于比较元素是否相等。
  • 返回值Except 方法返回一个 IEnumerable<TSource> 对象,其中 TSource 是输入序列中元素的类型。
public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> first,IEnumerable<TKey> second,Func<TSource, TKey> keySelector
)public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> first,IEnumerable<TKey> second,Func<TSource, TKey> keySelector,IEqualityComparer<TKey> comparer
)
  • 参数
    • first:第一个要计算差集的序列。
    • second:第二个要计算差集的序列(注意这里的元素类型是键类型 TKey)。
    • keySelector:一个函数,用于从每个元素中提取键值。
    • comparer(可选):一个 IEqualityComparer 实现,用于比较键值是否相等。
  • 返回值UnionBy 方法返回一个 IEnumerable<TSource> 对象,其中 TSource 是输入序列中元素的类型。

2)工作原理

  • Except:计算两个序列的差集,返回第一个序列中存在但第二个序列中不存在的所有元素,并使用默认或自定义的比较器来判断元素是否相等。
  • ExceptBy:根据指定的键选择器函数提取键值,并计算两个序列的差集,返回第一个序列中存在但第二个序列中不存在的所有元素,去除具有相同键值的重复项。

3)使用场景

适用于数据过滤、数据预处理、多个集合的差集计算等场景。

3. 使用示例

示例 1:基本差集计算

假设我们有两个整数列表,我们希望计算第一个列表中存在但第二个列表中不存在的所有元素。

class Program
{static void Main(){List<int> list1 = new List<int> { 1, 2, 3, 4, 5 };List<int> list2 = new List<int> { 3, 4, 6 };// 使用 Except 计算差集var exceptList = list1.Except(list2);Console.WriteLine(string.Join(",", exceptList));// 输出:1,2,5exceptList = list1.ExceptBy(list2, x => x);Console.WriteLine(string.Join(",", exceptList));// 输出:1,2,5}
}

示例 2:自定义对象

当处理自定义对象时,Union 方法默认使用对象的 EqualsGetHashCode 方法来判断元素是否相同。如果你有更复杂的比较需求,可以提供自定义的 IEqualityComparer<T> 实现。

  • 使用默认的 EqualsGetHashCode 方法,并不能实现对象内容的比较
class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 },new Person { Name = "Charlie", Age = 35 }};List<Person> list2 = new List<Person>{new Person { Name = "Bob", Age = 25 },new Person { Name = "David", Age = 40 }};// 使用 Except 计算差集var exceptPeople = list1.Except(list2);Console.WriteLine(string.Join(",", exceptPeople));// 输出:Alice (30),Bob (25),Charlie (35)}
}
  • 重写 对象的 EqualsGetHashCode 方法,可以实现对象内容的比较。使用Except时,默认就会调用重写后的方法判断对象是否相等
class Person
{public string Name { get; set; }public int Age { get; set; }public override bool Equals(object obj){if (obj is Person other){return Name == other.Name && Age == other.Age;}return false;}public override int GetHashCode(){return HashCode.Combine(Name, Age);}public override string ToString(){return $"{Name} ({Age})";}
}
class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "Bob", Age = 25 }};// 使用 Except 计算差集var exceptPeople = list1.Except(list2);Console.WriteLine(string.Join(",", exceptPeople));// 输出:Alice (30)}
}
  • 使用自定义的 PersonComparer 来比较 Person 对象。
class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}
class PersonComparer : IEqualityComparer<Person>
{public bool Equals(Person x, Person y){if (x == null || y == null) return false;return x.Name == y.Name && x.Age == y.Age;}public int GetHashCode(Person obj){return HashCode.Combine(obj.Name, obj.Age);}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "Bob", Age = 25 }};// 使用 Except 计算差集并使用自定义比较器var exceptPeople = list1.Except(list2, new PersonComparer());Console.WriteLine(string.Join(",", exceptPeople));// 输出:Alice (30)}
}
  • 使用ExceptBy ,通过指定键选择器函数来确定哪些对象应该被视为相同的。并确保合并后的结果中没有重复项。
class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 },new Person { Name = "Charlie", Age = 35 }};List<Person> list2 = new List<Person>{new Person { Name = "Bob", Age = 25 },new Person { Name = "David", Age = 40 }};// 使用 ExceptBy 计算差集并排除特定年龄var exceptPeople = list1.ExceptBy(list2.Select(x => x.Age), p => p.Age);Console.WriteLine(string.Join(",", exceptPeople));// 输出:Alice (30),Charlie (35)}
}

示例 3:处理无限序列

Except /ExceptBy方法采用惰性求值(Lazy Evaluation),这意味着它不会立即执行合并操作,而是等到实际遍历时才会计算结果。这使得 Except /ExceptBy 可以处理无限序列或延迟执行复杂的查询。

class Program
{static void Main(){IEnumerable<int> infiniteNumbers = Enumerable.Range(0, int.MaxValue).Select(i => i * 2);List<int> finiteNumbers = new List<int> { 1, 3, 5 };// 使用 Union 合并无限序列和有限序列//var unionedSequence = infiniteNumbers.Except(finiteNumbers);var unionedSequence = infiniteNumbers.ExceptBy(finiteNumbers, x => x);// 限制输出数量Console.WriteLine("Unioned Sequence (First 10 elements):");foreach (var item in unionedSequence.Take(10)){Console.Write(item + " ");}}
}

输出结果:

Unioned Sequence (First 10 elements):
0 2 4 6 8 10 12 14 16 18

在这个例子中,我们展示了如何使用 Except /ExceptBy 方法合并一个无限序列和一个有限序列,并通过 Take 方法限制输出的数量,从而避免无限循环。

示例 4:自定义比较器

class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}class CustomAgeComparer : IEqualityComparer<int>
{public bool Equals(int x, int y){// 自定义比较逻辑:年龄相差不超过1岁视为相同return Math.Abs(x - y) <= 1;}public int GetHashCode(int obj){return 0;}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 },new Person { Name = "Charlie", Age = 35 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "David", Age = 26 }};// 使用 UnionBy 合并两个列表并根据年龄和自定义比较器去重var unionedPeople = list1.ExceptBy(list2.Select(x=>x.Age), p => p.Age, new CustomAgeComparer());Console.WriteLine(string.Join(",", unionedPeople));// 输出:Charlie (35)}
}

示例 5:多个集合的合并

当需要合并多个集合时,可以多次使用 Except/ExceptBy 方法。

class Program
{static void Main(){List<int> list1 = new List<int> { 1, 2, 3, 4, 5 };List<int> list2 = new List<int> { 3, 4, 6 };List<int> list3 = new List<int> { 4, 7, 8 };// 使用 Union 合并多个集合//var unionedLists = list1.Except(list2).Except(list3);var unionedLists = list1.ExceptBy(list2, x => x).ExceptBy(list3, x => x);Console.WriteLine(string.Join(",", unionedLists));// 输出:1,2,5}
}

4. 注意事项

尽管 Except/ExceptBy 方法非常有用,但在实际应用中也有一些需要注意的地方:

  • 空集合处理: 如果源集合为空,Except/ExceptBy 方法将返回一个空的结果集。因此,在使用 Except /ExceptBy 方法之前,通常不需要检查集合是否为空。
  • 数据类型一致:适用于需要取差集的集合对象的数据类型是一样的情况。

五、IntersectIntersectBy :交集

在这里插入图片描述

1. 什么是 Intersect/IntersectBy

  • Intersect 方法用于计算两个序列的交集,即返回两个序列中共有的所有元素。默认情况下,它使用对象的默认比较器(如 EqualityComparer<T>.Default)来比较元素是否相等。你也可以提供自定义的比较器来控制比较逻辑。
  • IntersectBy 是 .NET 6 及以上版本中引入的一个扩展方法,用于计算两个序列的交集,但与 Intersect 不同的是,它允许你通过指定的键选择器函数来确定元素是否相同。这意味着你可以根据某个特定属性或计算结果来进行交集操作,而不是直接比较整个对象。

2. Intersect/IntersectBy 方法 基本信息

1) Intersect/IntersectBy

public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first,IEnumerable<TSource> second
)public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first,IEnumerable<TSource> second,IEqualityComparer<TSource> comparer
)
  • 参数
    • first:第一个要计算交集的序列。
    • second:第二个要计算交集的序列。
    • comparer(可选):一个 IEqualityComparer<TSource> 实现,用于比较元素是否相等。
  • 返回值Except 方法返回一个 IEnumerable<TSource> 对象,其中 TSource 是输入序列中元素的类型。
public static IEnumerable<TSource> IntersectBy<TSource, TKey>(this IEnumerable<TSource> first,IEnumerable<TKey> second,Func<TSource, TKey> keySelector
)public static IEnumerable<TSource> IntersectBy<TSource, TKey>(this IEnumerable<TSource> first,IEnumerable<TKey> second,Func<TSource, TKey> keySelector,IEqualityComparer<TKey> comparer
)
  • 参数
    • first:第一个要计算交集的序列。
    • second:第二个要计算交集的序列(注意这里的元素类型是键类型 TKey)。
    • keySelector:一个函数,用于从每个元素中提取键值。
    • comparer(可选):一个 IEqualityComparer 实现,用于比较键值是否相等。
  • 返回值UnionBy 方法返回一个 IEnumerable<TSource> 对象,其中 TSource 是输入序列中元素的类型。

2)工作原理

  • Intersect:计算两个序列的交集,返回两个序列中共有的所有元素,并使用默认或自定义的比较器来判断元素是否相等。
  • IntersectBy:根据指定的键选择器函数提取键值,并计算两个序列的交集,返回第一个序列中具有与第二个序列中相同键值的所有元素。

3)使用场景

适用于数据过滤、数据预处理、多个集合的交集计算等场景。

3. 使用示例

示例 1:基本交集计算

假设我们有两个整数列表,我们希望找出它们共有的元素。

class Program
{static void Main(){List<int> list1 = new List<int> { 1, 2, 3, 4, 5 };List<int> list2 = new List<int> { 3, 4, 6 };// 使用 Intersect 计算交集var intersectList = list1.Intersect(list2);Console.WriteLine(string.Join(",", intersectList));// 输出:3,4intersectList = list1.IntersectBy(list2, x => x);Console.WriteLine(string.Join(",", intersectList));// 输出:3,4}
}

示例 2:自定义对象

当处理自定义对象时,Intersect 方法默认使用对象的 EqualsGetHashCode 方法来判断元素是否相同。如果你有更复杂的比较需求,可以提供自定义的 IEqualityComparer<T> 实现。

  • 使用默认的 EqualsGetHashCode 方法,并不能实现对象内容的比较
class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 },new Person { Name = "Charlie", Age = 35 }};List<Person> list2 = new List<Person>{new Person { Name = "Bob", Age = 25 },new Person { Name = "David", Age = 40 }};// 使用 Intersect 计算交集var intersectPeople = list1.Intersect(list2);Console.WriteLine(string.Join(",", intersectPeople));// 输出:          - 表示 没有交集}
}
  • 重写 对象的 EqualsGetHashCode 方法,可以实现对象内容的比较。使用Except时,默认就会调用重写后的方法判断对象是否相等
class Person
{public string Name { get; set; }public int Age { get; set; }public override bool Equals(object obj){if (obj is Person other){return Name == other.Name && Age == other.Age;}return false;}public override int GetHashCode(){return HashCode.Combine(Name, Age);}public override string ToString(){return $"{Name} ({Age})";}
}
class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "Bob", Age = 25 }};// 使用 Intersect 计算交集var intersectPeople = list1.Intersect(list2);Console.WriteLine(string.Join(",", intersectPeople));// 输出:Bob (25)}
}
  • 使用自定义的 PersonComparer 来比较 Person 对象。
class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}
class PersonComparer : IEqualityComparer<Person>
{public bool Equals(Person x, Person y){if (x == null || y == null) return false;return x.Name == y.Name && x.Age == y.Age;}public int GetHashCode(Person obj){return HashCode.Combine(obj.Name, obj.Age);}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "Bob", Age = 25 }};// 使用 Intersect 计算交集并使用自定义比较器var intersectPeople = list1.Intersect(list2, new PersonComparer());Console.WriteLine(string.Join(",", intersectPeople));// 输出:Bob (25)}
}
  • 使用ExceptBy ,通过指定键选择器函数来确定哪些对象应该被视为相同的。并确保合并后的结果中没有重复项。
class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 },new Person { Name = "Charlie", Age = 35 }};List<Person> list2 = new List<Person>{new Person { Name = "Bob", Age = 25 },new Person { Name = "David", Age = 40 }};// 使用 IntersectBy 计算交集var intersectPeople = list1.IntersectBy(list2.Select(x => x.Age), p => p.Age);Console.WriteLine(string.Join(",", intersectPeople));// 输出:Bob (25)}
}

示例 3:处理无限序列

Intersect /IntersectBy方法采用惰性求值(Lazy Evaluation),这意味着它不会立即执行合并操作,而是等到实际遍历时才会计算结果。这使得 Intersect /IntersectBy 可以处理无限序列或延迟执行复杂的查询。

class Program
{static void Main(){IEnumerable<int> infiniteNumbers = Enumerable.Range(0, int.MaxValue).Select(i => i * 2);List<int> finiteNumbers = new List<int> { 4, 6, 8 };// 使用 Intersect 计算交集var intersectSequence = infiniteNumbers.Intersect(finiteNumbers);// 限制输出数量Console.WriteLine("Elements common between infiniteNumbers and finiteNumbers (First 3 elements):");foreach (var item in intersectSequence.Take(3)){Console.Write(item + " ");}}
}

输出结果:

Elements common between infiniteNumbers and finiteNumbers (First 3 elements):
4 6 8

在这个例子中,我们展示了如何使用 Intersect 方法计算一个无限序列和一个有限序列之间的交集,并通过 Take 方法限制输出的数量,从而避免无限循环。

示例 4:自定义比较器

class Person
{public string Name { get; set; }public int Age { get; set; }public override string ToString(){return $"{Name} ({Age})";}
}class CustomAgeComparer : IEqualityComparer<int>
{public bool Equals(int x, int y){// 自定义比较逻辑:年龄相差不超过1岁视为相同return Math.Abs(x - y) <= 1;}public int GetHashCode(int obj){return 0;}
}class Program
{static void Main(){List<Person> list1 = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 },new Person { Name = "Charlie", Age = 35 }};List<Person> list2 = new List<Person>{new Person { Name = "Charlie", Age = 30 },new Person { Name = "David", Age = 26 }};// 使用 IntersectBy 取两个列表交集并根据年龄和自定义比较器 比较Person对象var intersectPeople = list1.IntersectBy(list2.Select(x => x.Age), p => p.Age, new CustomAgeComparer());Console.WriteLine(string.Join(",", intersectPeople));// 输出:Alice (30),Bob (25)}
}

示例 5:多个集合的合并

当需要合并多个集合时,可以多次使用 Intersect/IntersectBy 方法。

class Program
{static void Main(){List<int> list1 = new List<int> { 1, 2, 3, 4, 5 };List<int> list2 = new List<int> { 3, 4, 6 };List<int> list3 = new List<int> { 4, 7, 8 };// 使用 Union 合并多个集合//var unionedLists = list1.Intersect(list2).Intersect(list3);var unionedLists = list1.IntersectBy(list2, x => x).IntersectBy(list3, x => x);Console.WriteLine(string.Join(",", unionedLists));// 输出:4}
}

4. 注意事项

尽管 Intersect/IntersectBy方法非常有用,但在实际应用中也有一些需要注意的地方:

  • 空集合处理: 如果源集合为空, Intersect/IntersectBy 方法将返回一个空的结果集。因此,在使用 Intersect/IntersectBy方法之前,通常不需要检查集合是否为空。
  • 数据类型一致:适用于需要取差集的集合对象的数据类型是一样的情况。

结语

回到目录页:C#/.NET 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料:
微软官方文档 Enumerable

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/72379.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51c自动驾驶~合集54

我自己的原文哦~ https://blog.51cto.com/whaosoft/13517811 #Chameleon 快慢双系统&#xff01;清华&博世最新&#xff1a;无需训练即可解决复杂道路拓扑 在自动驾驶技术中&#xff0c;车道拓扑提取是实现无地图导航的核心任务之一。它要求系统不仅能检测出车道和交…

Spring Cloud Eureka - 高可用服务注册与发现解决方案

在微服务架构中&#xff0c;服务注册与发现是确保系统动态扩展和高效通信的关键。Eureka 作为 Spring Cloud 生态的核心组件&#xff0c;不仅提供去中心化的服务治理能力&#xff0c;还通过自我保护、健康检查等机制提升系统的稳定性&#xff0c;使其成为微服务架构中的重要支撑…

Unity屏幕适配——立项时设置

项目类型&#xff1a;2D游戏、竖屏、URP 其他类型&#xff0c;部分原理类似。 1、确定设计分辨率&#xff1a;750*1334 为什么是它&#xff1f; 因为它是 iphone8 的尺寸&#xff0c;宽高比适中。 方便后续适配到真机的 “更长屏” 或 “更宽屏” 2、在场景…

深度学习中LayerNorm与RMSNorm对比

LayerNorm不同于BatchNorm&#xff0c;其与batch大小无关&#xff0c;均值和方差 在 每个样本的特征维度 C 内计算&#xff0c; 适用于 变长输入&#xff08;如 NLP 任务中的 Transformer&#xff09; 详细的BatchNorm在之前的一篇文章进行了详细的介绍&#xff1a;深度学习中B…

使用WireShark解密https流量

概述 https协议是在http协议的基础上&#xff0c;使用TLS协议对http数据进行了加密&#xff0c;使得网络通信更加安全。一般情况下&#xff0c;使用WireShark抓取的https流量&#xff0c;数据都是加密的&#xff0c;无法直接查看。但是可以通过以下两种方法&#xff0c;解密抓…

Linux命令基础,创建,输入,输出,查看,查询

什么是命令、命令行 命令行&#xff1a;即&#xff1a;Linux终端&#xff08;Terminal&#xff09;&#xff0c;是一种命令提示符页面。以纯“字符”的形式操作操作系统&#xff0c;可以使用各种字符化命令对操作系统发出操作指令。 命令&#xff1a;即Linux程序。一个命令就…

【笔记】深度学习模型训练的 GPU 内存优化之旅:综述篇

开设此专题&#xff0c;目的一是梳理文献&#xff0c;目的二是分享知识。因为笔者读研期间的研究方向是单卡上的显存优化&#xff0c;所以最初思考的专题名称是“显存突围&#xff1a;深度学习模型训练的 GPU 内存优化之旅”&#xff0c;英文缩写是 “MLSys_GPU_Memory_Opt”。…

Vue 3 Diff 算法深度解析:与 Vue 2 双端比对对比

文章目录 1. 核心算法概述1.1 Vue 2 双端比对算法1.2 Vue 3 快速 Diff 算法 2. 算法复杂度分析2.1 时间复杂度对比2.2 空间复杂度对比 3. 核心实现解析3.1 Vue 2 双端比对代码3.2 Vue 3 快速 Diff 代码 4. 性能优化分析4.1 性能测试数据4.2 内存使用对比 5. 使用场景分析5.1 Vu…

神经网络的基本知识

感知机 输入&#xff1a;来自其他 n 个神经元传递过来的输入信号 处理&#xff1a;输入信号通过带权重的连接进行传递, 神经元接受到总输入值将与神经元的阈值进行比较 输出&#xff1a;通过激活函数的处理以得到输出 感知机由两层神经元组成, 输入层接受外界输入信号传递给…

C++相关基础概念之入门讲解(上)

1. 命名空间 C中的命名空间&#xff08;namespace&#xff09;是用来避免命名冲突问题的一种机制。通过将类、函数、变量等封装在命名空间中&#xff0c;可以避免不同部分的代码中出现相同名称的冲突。在C中&#xff0c;可以使用namespace关键字来定义命名空间。 然后我们在调…

网络协议栈

网络协议栈的位置 用户在应用层的各种请求最终会下达给操作系统&#xff0c;操作系统内除了进程管理、文件管理、内存管理、驱动管理之外&#xff0c;还有一个内嵌的软件协议栈&#xff0c;协议栈将用户的数据进行各种封包后&#xff0c;通过网卡将数据传递到网络当中&#xf…

C++之list类(超详细)

在上一节中我们学习了STL中的vector这个容器&#xff0c;这节我们来学习一下另外一个常用的容器——list。 文章目录 前言 一、list的介绍 二、list的使用及相关接口 1.list的使用 2.list的迭代器使用 3.list的相关接口 3.1 list capacity 3.2 list element access 3.3…

mysql、oracle、SQLserver之间的区别和优势

MySQL、Oracle和SQL Server都是常见的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它们在某些方面有一些区别和优势。 MySQL&#xff1a; MySQL是一种开源的RDBMS&#xff0c;由Oracle公司开发和维护。它具有快速、稳定和易于使用的特点。MySQL适用于中小型…

75.HarmonyOS NEXT ImageItemView组件深度剖析:手势交互与动画实现(二)

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT ImageItemView组件深度剖析&#xff1a;手势交互与动画实现(二) 一、手势系统架构 .gesture(GestureGroup(GestureMode.Exclusiv…

Qt 控件概述 QWdiget

Qt为我们提供了很多控件&#xff0c;这些控件拿过来就可以使用 目录 QWidget 属性 WindowFrame的影响 QWidget Qt中所有的组件都是继承自QWidget Qt Creator中的右侧可以看到QWidget的各种属性 其中各种属性都可以在Qt文档中找到说明 ​ 属性 enabled&#xff1a;描述该组…

适合企业内训的AI工具实操培训教程(37页PPT)(文末有下载方式)

详细资料请看本解读文章的最后内容。 资料解读&#xff1a;适合企业内训的 AI 工具实操培训教程 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;技术迅速发展&#xff0c;深度融入到各个领域&#xff0c;AIGC&#xff08;人工智能生成内容&#xff09;更是成…

Spring Boot对接twilio发送邮件信息

要在Spring Boot应用程序中对接Twilio发送邮件信息&#xff0c;您可以使用Twilio的SendGrid API。以下是一个简单的步骤指南&#xff0c;帮助您完成这一过程&#xff1a; 1. 创建Twilio账户并获取API密钥 注册一个Twilio账户&#xff08;如果您还没有的话&#xff09;。在Twi…

【最后203篇系列】015 几种消息队列的思考

背景 队列还是非常重要的中间件&#xff0c;可以帮助我们&#xff1a;提高处理效率、完成更复杂的处理流程 最初&#xff0c;我觉得只要掌握一种消息队列就够了&#xff0c;现在想想挺好笑的。 过去的探索 因为我用python&#xff0c;而rabbitmq比较贴合快速和复杂的数据处…

TensorFlow 与 TensorFlow Lite:核心解析与层应用

1. 引言 TensorFlow 是 Google 开发的开源机器学习框架&#xff0c;支持从数据预处理、模型训练到推理部署的完整生命周期。然而&#xff0c;在嵌入式和移动设备上&#xff0c;原生 TensorFlow 过于庞大&#xff0c;因此 Google 推出了轻量级版本——TensorFlow Lite&#xff…

DeepSeek大模型在政务服务领域的应用

DeepSeek大模型作为国产人工智能技术的代表&#xff0c;近年来在政务服务领域的应用呈现多点开花的态势。通过多地实践&#xff0c;该技术不仅显著提升了政务服务的效率与智能化水平&#xff0c;还推动了政府治理模式的创新。以下从技术应用场景、典型案例及发展趋势三个维度进…