You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

414 lines
12 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using System.Collections.Immutable;
namespace LinqStudy.Test.LinqToObject
{
/// <summary>
/// Sets 集合操作符
/// 注意:集合操作为 “延迟执行”数据源为null时均引发异常。
/// </summary>
public class SetsTest
{
#region Distinct
/// <summary>
/// Distinct元素去重;延迟执行。
/// 注意:值类型可以直接去重;引用类型比较的是引用而不是对象本身的属性等,可以提供自定义比较器。
/// </summary>
[Fact]
public void Distinct_Test()
{
List<int> array = new List<int>() { 1, 2, 2, 3, 3, 3 };
var distinctItem = array.Distinct();
var expected = new List<int>() { 1, 2, 3 };
Assert.Equal(expected, distinctItem);
}
/// <summary>
/// 引用类型:剔除同一个引用的重复项。
/// </summary>
[Fact]
public void Distinct_Reference_Yes_Test()
{
var p1 = new Person() { Id = 2, Name = "小龙女", Age = 28 };
var p2 = new Person() { Id = 4, Name = "杨过", Age = 32 };
List<Person> peoples = new List<Person>();
peoples.Add(p1);
peoples.Add(p2);
//添加对同一对象的多次引用
peoples.Add(p1);
peoples.Add(p2);
var totalCount = peoples.Count();
var distinctCount = peoples.Distinct().Count();
Assert.Equal(4, totalCount);
Assert.Equal(2, distinctCount);
}
[Fact]
public void Distinct_Reference_No_Test()
{
List<Person> peoples = new List<Person>()
{
new Person() { Id = 1, Name = "小龙女", Age = 28 },
new Person() { Id = 1, Name = "小龙女", Age = 28 },
};
//虽然1、2两项对象属性完命相同但是两个不同的对象(new两次),所以不是“重复项”
//去重后仍然是2项
var distinctCount = peoples.Distinct().Count();
Assert.Equal(2, distinctCount);
}
/// <summary>
/// 延迟执行
/// </summary>
[Fact]
public void Distinct_Daley_Test()
{
List<int> array = new List<int>() { 1, 2, 2, 3, 3, 3 };
var distinctItem = array.Distinct();
array.Add(5);
var expected = new List<int>() { 1, 2, 3, 5 };
Assert.Equal(expected, distinctItem);
}
/// <summary>
/// 重载:自定义比较器
/// </summary>
[Fact]
public void Distinct_compare_Test()
{
List<Person> peoples = new List<Person>()
{
new Person(){ Id=1, Name="小龙女", Age=28},
new Person(){ Id=1, Name="我不是龙女", Age=68},
};
var distinctItem = peoples.Distinct(new PersonEqualityComparerById());
//虽然两项只有Id属性相等其它属性均不同
//但是因为自定义比较器内部只比较Id即只要Id相同就认为同一对象。
//所以去重后,只有一项(第一项,第二项被认为是重复项,被去除)。
var distinctCount = distinctItem.Count();
var expected = 1;
Assert.Equal(expected, distinctCount);
}
#endregion
#region Union
///<summary>
/// Union:取两个序列的并集,并去除重复项。
/// 与SQL比较相似Concat不去除重复项。
///</summary>
[Fact]
public void Union_Test()
{
var p1 = new Person() { Id = 1, Name = "杨过", Age = 32 };
var p2 = new Person() { Id = 2, Name = "小龙女", Age = 28 };
var p3 = new Person() { Id = 3, Name = "云花公主", Age = 16 };
List<Person> peoples1 = new List<Person>()
{
p1,
p2,
};
List<Person> peoples2 = new List<Person>()
{
p1,
p3,
};
var act = peoples1.Union(peoples2);
//因为"杨过"是重复的所有总共有3项
var totalCount = act.Count();
Assert.Equal(3, totalCount);
}
///<summary>
/// Union: 对同一数据源两次查询后两次结果Union
/// 注意:同一数据源多次查询形成的序列项,均是对同一对象的引用。
/// 项里保存的是引用地址,非对象本身。
///</summary>
[Fact]
public void Union_UseQuery_Test()
{
List<Person> peoples = new List<Person>()
{
new Person(){ Id=1, Name="张三丰", Age=230},
new Person(){ Id=2, Name="小龙女", Age=28},
new Person(){ Id=3, Name="云花公主", Age=16},
new Person(){ Id=4, Name="杨过", Age=32},
};
var peoples1 = peoples.Where(q => q.Id <= 3);
var peoples2 = peoples.Where(q => q.Age < 230);
var act = peoples1.Union(peoples2);
//前3项 + 后3项- 重复2项=4项
var totalCount = act.Count();
Assert.Equal(4, totalCount);
}
///<summary>
/// Union重载: camparer
///</summary>
[Fact]
public void Union_camparer_Test()
{
var p1 = new Person() { Id = 1, Name = "杨过", Age = 32 };
var p2 = new Person() { Id = 2, Name = "小龙女", Age = 28 };
var p3 = new Person() { Id = 2, Name = "我非龙女", Age = 77 };
List<Person> peoples1 = new List<Person>()
{
p1,
p2,
};
List<Person> peoples2 = new List<Person>()
{
p1,
p3,
};
var act = peoples1.Union
(
peoples2,
new PersonEqualityComparerById()
)
.ToList();
//虽然P2和p3只有Id相同其它不同但自定义比较只看Id所以P2和p3被认为是同一个对象。
//结果集为p1+p2
var totalCount = act.Count();
Assert.Equal(2, totalCount);
}
///<summary>
/// 异常ArgumentNullException
///</summary>
[Fact]
public void Union_ArgumentNullException_Test()
{
List<Person> peoples1 = null;
List<Person> peoples2 = null;
Action act = () => peoples1.Union
(
peoples2
);
Assert.Throws<ArgumentNullException>(act);
}
#endregion
#region Intersect
///<summary>
/// Intersect: 取交集
///</summary>
[Fact]
public void Intersect_Test()
{
var p1 = new Person() { Id = 1, Name = "杨过", Age = 32 };
var p2 = new Person() { Id = 2, Name = "小龙女", Age = 28 };
var p3 = new Person() { Id = 3, Name = "云花公主", Age = 16 };
List<Person> peoples1 = new List<Person>()
{
p1,p2,
};
List<Person> peoples2 = new List<Person>()
{
p1,p3,
};
var intesectItem = peoples1.Intersect(peoples2);
var itemCount = intesectItem.Count();
Assert.Equal(1, itemCount);
}
///<summary>
/// 引用类型:使用
///</sumaary>
[Fact]
public void Intersect_Reference_Test()
{
List<Person> peoples1 = new List<Person>()
{
new Person(){ Id=1, Name="杨过", Age=32},
new Person(){ Id=2, Name="小龙女", Age=28},
};
List<Person> peoples2 = new List<Person>()
{
new Person(){ Id=2, Name="小龙女", Age=28},
new Person(){ Id=3, Name="云花公主", Age=16},
};
//虽然两个“小龙女”属性相同,但不是一个对象,没有交集。
var intesectItem = peoples1.Intersect(peoples2);
Assert.Empty(intesectItem);
}
///<summary>
/// 重载:自定义比较器 comparer
///</sumaary>
[Fact]
public void Intersect_comparer_Test()
{
List<Person> peoples1 = new List<Person>()
{
new Person(){ Id=1, Name="杨过", Age=32},
new Person(){ Id=2, Name="小龙女", Age=28},
};
List<Person> peoples2 = new List<Person>()
{
new Person(){ Id=2, Name="小龙女", Age=28},
new Person(){ Id=3, Name="云花公主", Age=16},
};
//虽然两个“小龙女”属性相同,但不是一个对象,没有交集。
var intesectItem = peoples1.Intersect(peoples2, new PersonEqualityComparerById());
var intesctItemName = intesectItem.First().Name;
Assert.Equal("小龙女", intesctItemName);
}
#endregion
#region Intersect
///<summary>
/// Except: 从一个序列中排除另一个序列中的项。
///</summary>
[Fact]
public void Except_Test()
{
var p1 = new Person() { Id = 1, Name = "杨过", Age = 32 };
var p2 = new Person() { Id = 2, Name = "小龙女", Age = 28 };
var p3 = new Person() { Id = 3, Name = "云花公主", Age = 16 };
List<Person> peoples1 = new List<Person>()
{
p1,p2,
};
List<Person> peoples2 = new List<Person>()
{
p1,p3,
};
var exceptItem = peoples1.Except(peoples2);
var itemName = exceptItem.First().Name;
Assert.Equal("小龙女", itemName);
}
///<summary>
/// 引用类型:使用
///</sumaary>
[Fact]
public void Except_Reference_Test()
{
List<Person> peoples1 = new List<Person>()
{
new Person(){ Id=1, Name="杨过", Age=32},
new Person(){ Id=2, Name="小龙女", Age=28},
};
List<Person> peoples2 = new List<Person>()
{
new Person(){ Id=2, Name="小龙女", Age=28},
new Person(){ Id=3, Name="云花公主", Age=16},
};
var exceptItem = peoples1.Except(peoples2);
var itemCount = exceptItem.Count();
Assert.Equal(2, itemCount);
}
///<summary>
/// 重载:自定义比较器 comparer
///</sumaary>
[Fact]
public void Except_comparer_Test()
{
List<Person> peoples1 = new List<Person>()
{
new Person(){ Id=1, Name="杨过", Age=32},
new Person(){ Id=2, Name="小龙女", Age=28},
};
List<Person> peoples2 = new List<Person>()
{
new Person(){ Id=2, Name="小龙女", Age=28},
new Person(){ Id=3, Name="云花公主", Age=16},
};
var exceptItem = peoples1.Except(peoples2, new PersonEqualityComparerById());
var iexcepItemName = exceptItem.First().Name;
Assert.Equal("杨过", iexcepItemName);
}
#endregion
#region 串联操作:Concat
///<summary>
/// Concat将两个序列合并成一个序列不去重。与Union不同。
///<summary>
[Fact]
public void Concat_Test()
{
List<Person> peoples1 = new List<Person>()
{
new Person(){ Id=2, Name="小龙女", Age=28},
new Person(){ Id=4, Name="杨过", Age=32},
};
List<Person> peoples2 = new List<Person>()
{
new Person(){ Id=2, Name="小龙女", Age=28},
new Person(){ Id=3, Name="云花公主", Age=16},
};
var concatAct = peoples1.Concat(peoples2);
var totalCount = concatAct.Count();
Assert.Equal(4, totalCount);
}
#endregion
}
}