2010-06-24 55 views
1

我有兩個類別:LINQ內加入

List<int> ids; 
List<User> users; 

User具有ID,姓名等

我想內部連接這兩個集合,並與來自第一ID返回一個新List<int>集合也在第二個集合中(用戶標識)。

我是LINQ的新手,不知道從哪裏開始。

謝謝。

回答

9

你並不需要用加入要做到這一點:

List<int> commonIds = ids.Intersect(users.Select(u => u.Id)).ToList(); 

編輯:針對在評論的問題,你可以得到用戶的列表,而無需使用Join

var matchingUsers = users.Where(u => ids.Contains(u.Id)); 

但是這是非常低效的,因爲Where子句必須掃描每個用戶的id列表。我想加入將處理這種情況的最好辦法:

List<User> matchingUsers = users.Join(ids, u => u.Id, id => id, (user, id) => user).ToList(); 
+0

你打我吧;) – 2010-06-24 23:02:21

+0

假設OP想要用戶,而不是ID。它還可以在不加入連接的情況下完成嗎? – spender 2010-06-24 23:07:18

+0

剛剛意識到我的id實際上是long和intersect函數,默認情況下只對int集合起作用(?)。 – 2010-06-25 01:07:26

2

在關係數據庫術語,內部聯接產生一個結果集,其中第一集合中的每個元素出現一次,每適配體在第二採集。如果第一個集合中的元素沒有匹配的元素,它不會出現在結果集中。 Join方法由C#中的join子句調用,實現了內部聯接。

本主題說明了如何進行內部的四個變體加入:

  • 簡單內加入該關聯基於一個簡單的按鍵兩個數據源 元素。

  • 一個內部聯接,它基於 複合鍵將來自兩個數據源的元素關聯起來。組合鍵是一個由多個值組成的鍵,使您可以根據比一個屬性更多的 關聯元素。

  • 多次連接,其中連續的連接操作被相互追加到 之間。

  • 通過使用組連接實現的內部連接。

例 簡單密鑰加入實施例

下面的示例創建含有兩個用戶定義類型,Person和寵物的對象兩個集合。查詢使用C#中的join子句將Person對象與其所有者爲Person的Pet對象進行匹配。 C#中的select子句定義了結果對象的外觀。在這個例子中,結果對象是由所有者的名字和寵物名稱組成的匿名類型。 C#

class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

class Pet 
{ 
    public string Name { get; set; } 
    public Person Owner { get; set; } 
} 

/// <summary> 
/// Simple inner join. 
/// </summary> 
public static void InnerJoinExample() 
{ 
    Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" }; 
    Person terry = new Person { FirstName = "Terry", LastName = "Adams" }; 
    Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" }; 
    Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" }; 
    Person rui = new Person { FirstName = "Rui", LastName = "Raposo" }; 

    Pet barley = new Pet { Name = "Barley", Owner = terry }; 
    Pet boots = new Pet { Name = "Boots", Owner = terry }; 
    Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte }; 
    Pet bluemoon = new Pet { Name = "Blue Moon", Owner = rui }; 
    Pet daisy = new Pet { Name = "Daisy", Owner = magnus }; 

    // Create two lists. 
    List<Person> people = new List<Person> { magnus, terry, charlotte, arlene, rui }; 
    List<Pet> pets = new List<Pet> { barley, boots, whiskers, bluemoon, daisy }; 

    // Create a collection of person-pet pairs. Each element in the collection 
    // is an anonymous type containing both the person's name and their pet's name. 
    var query = from person in people 
       join pet in pets on person equals pet.Owner 
       select new { OwnerName = person.FirstName, PetName = pet.Name }; 

    foreach (var ownerAndPet in query) 
    { 
     Console.WriteLine("\"{0}\" is owned by {1}", ownerAndPet.PetName, ownerAndPet.OwnerName); 
    } 
} 

// This code produces the following output: 
// 
// "Daisy" is owned by Magnus 
// "Barley" is owned by Terry 
// "Boots" is owned by Terry 
// "Whiskers" is owned by Charlotte 
// "Blue Moon" is owned by Rui 

注意,Person對象,其名字是「哈夫」沒有出現在結果集中,因爲那裏是具有Pet.Owner等於人沒有寵物的對象。 示例 複合鍵加入示例

除了基於一個屬性關聯元素外,還可以使用組合鍵來根據多個屬性比較元素。爲此,請爲每個集合指定鍵選擇器函數,以返回由要比較的屬性組成的匿名類型。如果標註屬性,則每個鍵的匿名類型中必須具有相同的標籤。這些屬性也必須以相同的順序出現。

以下示例使用Employee對象列表和Student對象列表來確定哪些員工也是學生。這兩種類型都有一個String類型的FirstName和LastName屬性。從每個列表元素創建連接鍵的函數返回一個由每個元素的FirstName和LastName屬性組成的匿名類型。連接操作比較這些組合鍵是否相等,並返回每個列表中名稱和姓氏匹配的對象對。 C#

class Employee 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int EmployeeID { get; set; } 
} 

class Student 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int StudentID { get; set; } 
} 

/// <summary> 
/// Performs a join operation using a composite key. 
/// </summary> 
public static void CompositeKeyJoinExample() 
{ 
    // Create a list of employees. 
    List<Employee> employees = new List<Employee> { 
     new Employee { FirstName = "Terry", LastName = "Adams", EmployeeID = 522459 }, 
     new Employee { FirstName = "Charlotte", LastName = "Weiss", EmployeeID = 204467 }, 
     new Employee { FirstName = "Magnus", LastName = "Hedland", EmployeeID = 866200 }, 
     new Employee { FirstName = "Vernette", LastName = "Price", EmployeeID = 437139 } }; 

    // Create a list of students. 
    List<Student> students = new List<Student> { 
     new Student { FirstName = "Vernette", LastName = "Price", StudentID = 9562 }, 
     new Student { FirstName = "Terry", LastName = "Earls", StudentID = 9870 }, 
     new Student { FirstName = "Terry", LastName = "Adams", StudentID = 9913 } }; 

    // Join the two data sources based on a composite key consisting of first and last name, 
    // to determine which employees are also students. 
    IEnumerable<string> query = from employee in employees 
           join student in students 
           on new { employee.FirstName, employee.LastName } 
           equals new { student.FirstName, student.LastName } 
           select employee.FirstName + " " + employee.LastName; 

    Console.WriteLine("The following people are both employees and students:"); 
    foreach (string name in query) 
     Console.WriteLine(name); 
} 

// This code produces the following output: 
// 
// The following people are both employees and students: 
// Terry Adams 
// Vernette Price 

例 多重聯實施例

任何數量的連接操作的可以被附加到彼此以執行多個連接。 C#中的每個連接子句都將指定的數據源與前一個連接的結果關聯起來。

以下示例創建三個集合:一個Person對象列表,一個Cat對象列表以及一個Dog對象列表。

C#中的第一個連接子句根據與Cat.Owner匹配的Person對象匹配人員和貓。它返回一系列包含Person對象和Cat.Name的匿名類型。

C#中的第二個連接子句基於由Person類型的Owner屬性組成的組合鍵,將第一個連接返回的匿名類型與提供的Dog列表中的Dog對象相關聯,動物的名字。它返回包含每個匹配對的Cat.Name和Dog.Name屬性的匿名類型序列。因爲這是一個內部連接,所以只返回第一個數據源中第二個數據源中匹配的那些對象。 C#

class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

class Pet 
{ 
    public string Name { get; set; } 
    public Person Owner { get; set; } 
} 

class Cat : Pet 
{ } 

class Dog : Pet 
{ } 

public static void MultipleJoinExample() 
{ 
    Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" }; 
    Person terry = new Person { FirstName = "Terry", LastName = "Adams" }; 
    Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" }; 
    Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" }; 
    Person rui = new Person { FirstName = "Rui", LastName = "Raposo" }; 
    Person phyllis = new Person { FirstName = "Phyllis", LastName = "Harris" }; 

    Cat barley = new Cat { Name = "Barley", Owner = terry }; 
    Cat boots = new Cat { Name = "Boots", Owner = terry }; 
    Cat whiskers = new Cat { Name = "Whiskers", Owner = charlotte }; 
    Cat bluemoon = new Cat { Name = "Blue Moon", Owner = rui }; 
    Cat daisy = new Cat { Name = "Daisy", Owner = magnus }; 

    Dog fourwheeldrive = new Dog { Name = "Four Wheel Drive", Owner = phyllis }; 
    Dog duke = new Dog { Name = "Duke", Owner = magnus }; 
    Dog denim = new Dog { Name = "Denim", Owner = terry }; 
    Dog wiley = new Dog { Name = "Wiley", Owner = charlotte }; 
    Dog snoopy = new Dog { Name = "Snoopy", Owner = rui }; 
    Dog snickers = new Dog { Name = "Snickers", Owner = arlene }; 

    // Create three lists. 
    List<Person> people = 
     new List<Person> { magnus, terry, charlotte, arlene, rui, phyllis }; 
    List<Cat> cats = 
     new List<Cat> { barley, boots, whiskers, bluemoon, daisy }; 
    List<Dog> dogs = 
     new List<Dog> { fourwheeldrive, duke, denim, wiley, snoopy, snickers }; 

    // The first join matches Person and Cat.Owner from the list of people and 
    // cats, based on a common Person. The second join matches dogs whose names start 
    // with the same letter as the cats that have the same owner. 
    var query = from person in people 
       join cat in cats on person equals cat.Owner 
       join dog in dogs on 
       new { Owner = person, Letter = cat.Name.Substring(0, 1) } 
       equals new { dog.Owner, Letter = dog.Name.Substring(0, 1) } 
       select new { CatName = cat.Name, DogName = dog.Name }; 

    foreach (var obj in query) 
    { 
     Console.WriteLine(
      "The cat \"{0}\" shares a house, and the first letter of their name, with \"{1}\".", 
      obj.CatName, obj.DogName); 
    } 
} 

// This code produces the following output: 
// 
// The cat "Daisy" shares a house, and the first letter of their name, with "Duke". 
// The cat "Whiskers" shares a house, and the first letter of their name, with "Wiley". 

例 內部聯接,通過使用分組加入實施例

以下示例說明如何實現由使用一組連接的內連接。

在查詢1中,Person對象列表根據匹配Pet.Owner屬性的Person,被組加入到Pet對象列表中。組聯接創建一箇中間組的集合,其中每個組由一個Person對象和一系列匹配的Pet對象組成。

通過在查詢中添加第二個從句,該序列序列被合併(或展平)爲一個更長的序列。最終序列的元素類型由select子句指定。在此示例中,該類型是由每個匹配對的Person.FirstName和Pet.Name屬性組成的匿名類型。

query1的結果等同於通過使用不帶into子句的join子句執行內部連接而獲得的結果集。 query2變量演示了這個等價的查詢。 C#

class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

class Pet 
{ 
    public string Name { get; set; } 
    public Person Owner { get; set; } 
} 

/// <summary> 
/// Performs an inner join by using GroupJoin(). 
/// </summary> 
public static void InnerGroupJoinExample() 
{ 
    Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" }; 
    Person terry = new Person { FirstName = "Terry", LastName = "Adams" }; 
    Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" }; 
    Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" }; 

    Pet barley = new Pet { Name = "Barley", Owner = terry }; 
    Pet boots = new Pet { Name = "Boots", Owner = terry }; 
    Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte }; 
    Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry }; 
    Pet daisy = new Pet { Name = "Daisy", Owner = magnus }; 

    // Create two lists. 
    List<Person> people = new List<Person> { magnus, terry, charlotte, arlene }; 
    List<Pet> pets = new List<Pet> { barley, boots, whiskers, bluemoon, daisy }; 

    var query1 = from person in people 
       join pet in pets on person equals pet.Owner into gj 
       from subpet in gj 
       select new { OwnerName = person.FirstName, PetName = subpet.Name }; 

    Console.WriteLine("Inner join using GroupJoin():"); 
    foreach (var v in query1) 
    { 
     Console.WriteLine("{0} - {1}", v.OwnerName, v.PetName); 
    } 

    var query2 = from person in people 
       join pet in pets on person equals pet.Owner 
       select new { OwnerName = person.FirstName, PetName = pet.Name }; 

    Console.WriteLine("\nThe equivalent operation using Join():"); 
    foreach (var v in query2) 
     Console.WriteLine("{0} - {1}", v.OwnerName, v.PetName); 
} 

// This code produces the following output: 
// 
// Inner join using GroupJoin(): 
// Magnus - Daisy 
// Terry - Barley 
// Terry - Boots 
// Terry - Blue Moon 
// Charlotte - Whiskers 
// 
// The equivalent operation using Join(): 
// Magnus - Daisy 
// Terry - Barley 
// Terry - Boots 
// Terry - Blue Moon 
// Charlotte - Whiskers 

編譯代碼

  • Visual Studio創建一個新的控制檯應用程序項目。

  • 添加對System.Core.dll的引用,如果它尚未引用。

  • 包含System.Linq命名空間。

  • 將示例中的代碼複製並粘貼到Main方法下方的program.cs文件 中。將一行代碼添加到Main方法中,以便調用 您粘貼的方法。

  • 運行該程序。

+0

尼斯努力在具有詳細答案,儘管簡潔在可能的情況下是首選。 – 2017-12-04 22:21:07