Select
와 SelectMany
의 차이점을 검색했지만 적절한 답변을 찾지 못했습니다. LINQ To SQL을 사용할 때 차이점을 배워야 하지만 내가 찾은 것은 표준 배열 예제뿐입니다.
누군가 LINQ To SQL 예제를 제공할 수 있습니까?
질문자 :Tarik
Select
와 SelectMany
의 차이점을 검색했지만 적절한 답변을 찾지 못했습니다. LINQ To SQL을 사용할 때 차이점을 배워야 하지만 내가 찾은 것은 표준 배열 예제뿐입니다.
누군가 LINQ To SQL 예제를 제공할 수 있습니까?
SelectMany
는 목록 목록을 반환하는 쿼리를 병합합니다. 예를 들어
public class PhoneNumber { public string Number { get; set; } } public class Person { public IEnumerable<PhoneNumber> PhoneNumbers { get; set; } public string Name { get; set; } } IEnumerable<Person> people = new List<Person>(); // Select gets a list of lists of phone numbers IEnumerable<IEnumerable<PhoneNumber>> phoneLists = people.Select(p => p.PhoneNumbers); // SelectMany flattens it to just a list of phone numbers. IEnumerable<PhoneNumber> phoneNumbers = people.SelectMany(p => p.PhoneNumbers); // And to include data from the parent in the result: // pass an expression to the second parameter (resultSelector) in the overload: var directory = people .SelectMany(p => p.PhoneNumbers, (parent, child) => new { parent.Name, child.Number });
많은 것을 선택하는 것은 외적을 취하는 SQL의 교차 조인 작업과 같습니다.
예를 들어
Set A={a,b,c} Set B={x,y}
많은 것을 선택하여 다음 세트를 얻을 수 있습니다.
{ (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) }
여기에서 집합 A와 집합 B의 요소에서 만들 수 있는 모든 가능한 조합을 사용합니다.
다음은 시도할 수 있는 LINQ 예제입니다.
List<string> animals = new List<string>() { "cat", "dog", "donkey" }; List<int> number = new List<int>() { 10, 20 }; var mix = number.SelectMany(num => animals, (n, a) => new { n, a });
믹스에는 다음과 같은 평평한 구조의 요소가 있습니다.
{(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}
var players = db.SoccerTeams.Where(c => c.Country == "Spain") .SelectMany(c => c.players); foreach(var player in players) { Console.WriteLine(player.LastName); }
...
SelectMany()
Select()
또는 루프가 필요한 방식으로 다차원 시퀀스를 축소할 수 있습니다.
자세한 내용은 이 블로그 게시물 을 참조하십시오.
SelectMany
대한 여러 오버로드가 있습니다. 그 중 하나를 사용하면 계층을 순회하는 동안 부모와 자식 간의 관계를 추적할 수 있습니다.
예 : 다음 구조가 있다고 가정합니다. League -> Teams -> Player
.
플레이어의 플랫 컬렉션을 쉽게 반환할 수 있습니다. 그러나 플레이어가 속한 팀에 대한 참조를 잃을 수 있습니다.
다행히도 이러한 목적을 위한 과부하가 있습니다.
var teamsAndTheirLeagues = from helper in leagues.SelectMany ( l => l.Teams , ( league, team ) => new { league, team } ) where helper.team.Players.Count > 2 && helper.league.Teams.Count < 10 select new { LeagueID = helper.league.ID , Team = helper.team };
이전 예제는 Dan의 IK 블로그 에서 가져왔습니다. 꼭 보시길 강력 추천합니다.
SelectMany
가 조인 바로 가기처럼 작동하는 것을 이해합니다.
따라서 다음을 수행할 수 있습니다.
var orders = customers .Where(c => c.CustomerName == "Acme") .SelectMany(c => c.Orders);
SelectMany() 메서드는 시퀀스의 각 요소가 별도인 시퀀스 를 병합하는 데 사용됩니다.
나는 이와 같은 user
가 있습니다.
class User { public string UserName { get; set; } public List<string> Roles { get; set; } }
기본:
var users = new List<User> { new User { UserName = "Reza" , Roles = new List<string>{"Superadmin" } }, new User { UserName = "Amin" , Roles = new List<string>{"Guest","Reseption" } }, new User { UserName = "Nima" , Roles = new List<string>{"Nurse","Guest" } }, }; var query = users.SelectMany(user => user.Roles, (user, role) => new { user.UserName, role }); foreach (var obj in query) { Console.WriteLine(obj); } //output //{ UserName = Reza, role = Superadmin } //{ UserName = Amin, role = Guest } //{ UserName = Amin, role = Reseption } //{ UserName = Nima, role = Nurse } //{ UserName = Nima, role = Guest }
시퀀스의 모든 항목에 대해 작업을 사용할 수 있습니다.
int[][] numbers = { new[] {1, 2, 3}, new[] {4}, new[] {5, 6 , 6 , 2 , 7, 8}, new[] {12, 14} }; IEnumerable<int> result = numbers .SelectMany(array => array.Distinct()) .OrderBy(x => x); //output //{ 1, 2 , 2 , 3, 4, 5, 6, 7, 8, 12, 14 }
List<List<int>> numbers = new List<List<int>> { new List<int> {1, 2, 3}, new List<int> {12}, new List<int> {5, 6, 5, 7}, new List<int> {10, 10, 10, 12} }; IEnumerable<int> result = numbers .SelectMany(list => list) .Distinct() .OrderBy(x=>x); //output // { 1, 2, 3, 5, 6, 7, 10, 12 }
선택은 소스 요소에서 결과 요소로의 간단한 일대일 투영입니다. Select Many는 쿼리 식에 여러 from 절이 있을 때 사용됩니다. 원래 시퀀스의 각 요소는 새 시퀀스를 생성하는 데 사용됩니다.
일부 SelectMany는 필요하지 않을 수 있습니다. 아래 2개의 쿼리는 동일한 결과를 제공합니다.
Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders) Orders.Where(o=>o.Customer.Name=="Tom")
일대다 관계의 경우,
from o in Orders join c in Customers on o.CustomerID equals c.ID where c.Name == "Tom" select o
너무 기술적이지 않으면서 - 많은 조직이 있는 데이터베이스, 각각 많은 사용자가 있는 데이터베이스:-
var orgId = "123456789"; var userList1 = db.Organizations .Where(a => a.OrganizationId == orgId) .SelectMany(a => a.Users) .ToList(); var userList2 = db.Users .Where(a => a.OrganizationId == orgId) .ToList();
둘 다 선택한 조직에 대해 동일한 ApplicationUser 목록을 반환합니다.
조직에서 사용자로의 첫 번째 "프로젝트", 두 번째는 사용자 테이블을 직접 쿼리합니다.
일부 기능적 프로그래머에게 도움이 될 수 있는 대체 보기를 위해:
Select
은 map
SelectMany
는 bind
(또는 Scala/Kotlin 사용자의 경우 flatMap
쿼리가 문자열(char 배열)을 반환할 때 더 명확합니다.
예를 들어 'Fruits' 목록에 'apple'이 포함된 경우
'선택'은 다음 문자열을 반환합니다.
Fruits.Select(s=>s) [0]: "apple"
'SelectMany'는 문자열을 평면화합니다.
Fruits.SelectMany(s=>s) [0]: 97 'a' [1]: 112 'p' [2]: 112 'p' [3]: 108 'l' [4]: 101 'e'
다음 예를 고려하십시오.
var array = new string[2] { "I like what I like", "I like what you like" }; //query1 returns two elements sth like this: //fisrt element would be array[5] :[0] = "I" "like" "what" "I" "like" //second element would be array[5] :[1] = "I" "like" "what" "you" "like" IEnumerable<string[]> query1 = array.Select(s => s.Split(' ')).Distinct(); //query2 return back flat result sth like this : // "I" "like" "what" "you" IEnumerable<string> query2 = array.SelectMany(s => s.Split(' ')).Distinct();
"SelectMany"가 여러 시퀀스에 걸쳐 평면화되고 투영되기 때문에 "I" 또는 "like"와 같은 중복 값이 query2에서 제거된 것을 볼 수 있습니다. 그러나 query1은 문자열 배열의 시퀀스를 반환합니다. 그리고 query1(첫 번째 및 두 번째 요소)에는 두 개의 다른 배열이 있으므로 아무 것도 제거되지 않습니다.
하위 배열 개체 데이터를 누적하기 위해 SelectMany + Select를 사용하는 방법의 또 다른 예입니다.
전화기를 가지고 있는 사용자가 있다고 가정합니다.
class Phone { public string BasePart = "555-xxx-xxx"; } class User { public string Name = "Xxxxx"; public List<Phone> Phones; }
이제 모든 사용자의 모든 전화기 BasePart를 선택해야 합니다.
var usersArray = new List<User>(); // array of arrays List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();
SelectMany 메서드는 IEnumerable<IEnumerable<T>>
을 IEnumerable<T>
SelectMany
공산주의와 마찬가지로 모든 요소는 동일한 방식으로 작동합니다(바보 같은 사람은 천재와 동일한 권리를 가짐).
var words = new [] { "a,b,c", "d,e", "f" }; var splitAndCombine = words.SelectMany(x => x.Split(',')); // returns { "a", "b", "c", "d", "e", "f" }
다음은 테스트를 위해 초기화된 소규모 컬렉션이 있는 코드 예제입니다.
class Program { static void Main(string[] args) { List<Order> orders = new List<Order> { new Order { OrderID = "orderID1", OrderLines = new List<OrderLine> { new OrderLine { ProductSKU = "SKU1", Quantity = 1 }, new OrderLine { ProductSKU = "SKU2", Quantity = 2 }, new OrderLine { ProductSKU = "SKU3", Quantity = 3 } } }, new Order { OrderID = "orderID2", OrderLines = new List<OrderLine> { new OrderLine { ProductSKU = "SKU4", Quantity = 4 }, new OrderLine { ProductSKU = "SKU5", Quantity = 5 } } } }; //required result is the list of all SKUs in orders List<string> allSKUs = new List<string>(); //With Select case 2 foreach loops are required var flattenedOrdersLinesSelectCase = orders.Select(o => o.OrderLines); foreach (var flattenedOrderLine in flattenedOrdersLinesSelectCase) { foreach (OrderLine orderLine in flattenedOrderLine) { allSKUs.Add(orderLine.ProductSKU); } } //With SelectMany case only one foreach loop is required allSKUs = new List<string>(); var flattenedOrdersLinesSelectManyCase = orders.SelectMany(o => o.OrderLines); foreach (var flattenedOrderLine in flattenedOrdersLinesSelectManyCase) { allSKUs.Add(flattenedOrderLine.ProductSKU); } //If the required result is flattened list which has OrderID, ProductSKU and Quantity, //SelectMany with selector is very helpful to get the required result //and allows avoiding own For loops what according to my experience do code faster when // hundreds of thousands of data rows must be operated List<OrderLineForReport> ordersLinesForReport = (List<OrderLineForReport>)orders.SelectMany(o => o.OrderLines, (o, ol) => new OrderLineForReport { OrderID = o.OrderID, ProductSKU = ol.ProductSKU, Quantity = ol.Quantity }).ToList(); } } class Order { public string OrderID { get; set; } public List<OrderLine> OrderLines { get; set; } } class OrderLine { public string ProductSKU { get; set; } public int Quantity { get; set; } } class OrderLineForReport { public string OrderID { get; set; } public string ProductSKU { get; set; } public int Quantity { get; set; } }
SelectMany()에 대한 공식적인 설명은 다음과 같습니다.
시퀀스의 각 요소를 IEnumerable에 투영하고 결과 시퀀스를 하나의 시퀀스로 병합합니다.
SelectMany()는 결과 시퀀스를 하나의 시퀀스로 병합하고 그 안의 각 요소에 대해 결과 선택기 함수를 호출합니다.
class PetOwner { public string Name { get; set; } public List<String> Pets { get; set; } } public static void SelectManyEx() { PetOwner[] petOwners = { new PetOwner { Name="Higa, Sidney", Pets = new List<string>{ "Scruffy", "Sam" } }, new PetOwner { Name="Ashkenazi, Ronen", Pets = new List<string>{ "Walker", "Sugar" } }, new PetOwner { Name="Price, Vernette", Pets = new List<string>{ "Scratches", "Diesel" } } }; // Query using SelectMany(). IEnumerable<string> query1 = petOwners.SelectMany(petOwner => petOwner.Pets); Console.WriteLine("Using SelectMany():"); // Only one foreach loop is required to iterate // through the results since it is a // one-dimensional collection. foreach (string pet in query1) { Console.WriteLine(pet); } // This code shows how to use Select() // instead of SelectMany(). IEnumerable<List<String>> query2 = petOwners.Select(petOwner => petOwner.Pets); Console.WriteLine("\nUsing Select():"); // Notice that two foreach loops are required to // iterate through the results // because the query returns a collection of arrays. foreach (List<String> petList in query2) { foreach (string pet in petList) { Console.WriteLine(pet); } Console.WriteLine(); } } /* This code produces the following output: Using SelectMany(): Scruffy Sam Walker Sugar Scratches Diesel Using Select(): Scruffy Sam Walker Sugar Scratches Diesel */
주요 차이점은 SelectMany()가 평평한 결과를 반환하는 동안 각 메서드의 결과입니다. Select()는 평평한 결과 집합 대신 목록 목록을 반환합니다.
따라서 SelectMany의 결과는 다음과 같은 목록입니다.
{스크러피, 샘, 워커, 설탕, 스크래치, 디젤}
하나의 foreach로 각 항목을 반복할 수 있습니다. 그러나 select의 결과로 쿼리가 배열 컬렉션을 반환하기 때문에 결과를 반복하기 위해 추가 foreach 루프가 필요합니다.
그것을 보는 또 다른 방법.
var src = new[] { 1, 2, 3, }; var map = src.Select(i => i.ToString()); var flatMap = src.SelectMany(i => /* go wild here producing IEnumerable's */); var empty = src.SelectMany(_ => new string[0]);
map
의 길이는 항상 src
의 길이와 일치합니다. map
의 요소는 변환이 무엇이든 - 위의 예에서 string
IEnumerable
경우 여전히 "래핑"됩니다.
flatMap
의 길이는 모든 iterable이 하나로 "뭉쳐지기" 때문에 각 요소에 제공된 변환에 따라 원하는 대로 됩니다. 따라서 극단적으로 src.Length = 3
이라는 사실에도 불구하고 empty
0
이 됩니다.
따라서 SelectMany
는 원래 IEnumerable
을 버리는 것으로 생각할 수 있습니다.
내가 생각하는 가장 좋은 이해 방법입니다.
var query = Enumerable .Range(1, 10) .SelectMany(ints => Enumerable.Range(1, 10), (a, b) => $"{a} * {b} = {a * b}") .ToArray(); Console.WriteLine(string.Join(Environment.NewLine, query)); Console.Read();
구구단 예.
출처 : http:www.stackoverflow.com/questions/958949/difference-between-select-and-selectmany
로컬 Git 브랜치를 원격 브랜치와 비교하는 방법 (0) | 2023.05.04 |
---|---|
"린팅"이란 무엇입니까? (0) | 2023.05.04 |
Twitter Bootstrap 3을 사용하여 열 중앙에 배치 (0) | 2023.05.04 |
쉘 스크립트에서 부울 변수를 어떻게 선언하고 사용할 수 있습니까? (0) | 2023.05.04 |
스크립트를 종료하는 방법? (0) | 2023.05.04 |