Ben arasındaki farkı arama oldum Select
ve SelectMany
ancak uygun bir cevap bulmak mümkün olmamıştır. LINQ To SQL kullanırken farkı öğrenmek gerekir ama tüm bulduğum standart dizi örnekleridir.
Birisi LINQ To SQL örneği sağlayabilir mi?
Ben arasındaki farkı arama oldum Select
ve SelectMany
ancak uygun bir cevap bulmak mümkün olmamıştır. LINQ To SQL kullanırken farkı öğrenmek gerekir ama tüm bulduğum standart dizi örnekleridir.
Birisi LINQ To SQL örneği sağlayabilir mi?
Yanıtlar:
SelectMany
liste listelerini döndüren sorguları düzleştirir. Örneğin
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 });
Birçoğu, SQL'de çapraz ürünü aldığı çapraz birleştirme işlemi gibidir .
Örneğin,
Set A={a,b,c}
Set B={x,y}
Aşağıdaki seti almak için birçok seçim kullanılabilir
{ (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) }
Burada, A kümesi ve B kümesi öğelerinden yapılabilecek tüm olası kombinasyonları aldığımızı unutmayın.
İşte deneyebileceğiniz bir LINQ örneği
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 });
karışım aşağıdaki gibi düz yapıda aşağıdaki öğelere sahip olacaktır:
{(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}
SelectMany
olduğunu . Daha ziyade, bu kullanılabilecek bir yoldur SelectMany
, ancak aslında bunu kullanmanın normal yolu değildir.
Where
sonra SelectMany koşulunu
var players = db.SoccerTeams.Where(c => c.Country == "Spain")
.SelectMany(c => c.players);
foreach(var player in players)
{
Console.WriteLine(player.LastName);
}
...
SelectMany()
çok boyutlu bir diziyi, aksi takdirde bir saniye Select()
veya döngü gerektirecek şekilde daraltmanıza olanak tanır .
Bu blog gönderisinde daha fazla ayrıntı .
Birkaç aşırı yükleme var SelectMany
. Bunlardan biri, hiyerarşiyi dolaşırken ebeveyn ve çocuklar arasındaki herhangi bir ilişkiyi izlemenize izin verir.
Örnek : Aşağıdaki yapıya sahip varsayalım: League -> Teams -> Player
.
Düz bir oyuncu koleksiyonuna kolayca geri dönebilirsiniz. Ancak, oyuncunun üyesi olduğu takıma herhangi bir referans kaybedebilirsiniz.
Neyse ki böyle bir amaç için aşırı yük var:
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
};
Önceki örnek Dan'ın IK blogundan alınmıştır . Şuna bir göz atmanızı şiddetle tavsiye ederim.
SelectMany
Birleştirme kısayolu gibi çalışmayı anlıyorum .
Böylece yapabilirsiniz:
var orders = customers
.Where(c => c.CustomerName == "Acme")
.SelectMany(c => c.Orders);
.SelectMany(c => new {c.CompanyName, c.Orders.ShippedDate});
işe yaramaz. SelectMany, liste listesini düzleştiriyor ve sonuç için içerilen listelerin herhangi birini (ancak her seferinde bir tane) seçebilirsiniz. Karşılaştırma için: Linq .
Bazı SelectMany gerekli olmayabilir. Aşağıdaki 2 sorgu aynı sonucu verir.
Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders)
Orders.Where(o=>o.Customer.Name=="Tom")
1-Çok-ilişki için,
from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o
Çok teknik olmadan - her biri birçok Kullanıcı ile birçok Organizasyon veritabanı: -
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();
her ikisi de seçilen Kuruluş için aynı ApplicationUser listesini döndürür .
Kuruluştan Kullanıcılara ilk "projeler", ikincisi Kullanıcılar tablosunu doğrudan sorgular.
Sorgu bir dize (karakter dizisi) döndürdüğünde daha açıktır:
Örneğin, 'Meyveler' listesi 'elma' içeriyorsa
'Seç' dizeyi döndürür:
Fruits.Select(s=>s)
[0]: "apple"
'SelectMany' dizeyi düzleştirir:
Fruits.SelectMany(s=>s)
[0]: 97 'a'
[1]: 112 'p'
[2]: 112 'p'
[3]: 108 'l'
[4]: 101 'e'
Sadece bazı fonksiyonel programcılara yardımcı olabilecek alternatif bir görünüm için:
Select
dır-dir map
SelectMany
olduğu bind
(ya flatMap
da Scala / Kotlin kişilik)Bu örneği düşünün:
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();
Gördüğünüz gibi "Select" gibi "I" veya "like" gibi yinelenen değerler kaldırıldı çünkü "SelectMany" birden çok diziyi düzleştiriyor ve projelendiriyor. Ancak query1, dize dizilerinin sırasını döndürür. ve sorgu1'de (birinci ve ikinci öğe) iki farklı dizi bulunduğundan, hiçbir şey kaldırılmaz.
Alt dizi nesneleri verilerini toplamak için SelectMany + Select'in nasıl kullanılabileceğine bir örnek daha.
Telefonları olan kullanıcılarımız olduğunu varsayalım:
class Phone {
public string BasePart = "555-xxx-xxx";
}
class User {
public string Name = "Xxxxx";
public List<Phone> Phones;
}
Şimdi tüm telefonların tüm kullanıcıların BaseParts'larını seçmemiz gerekiyor:
var usersArray = new List<User>(); // array of arrays
List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();
usersArray.SelectMany(ua => ua.Phones.Select(p => p.BasePart))
Test için başlatılmış küçük bir koleksiyona sahip bir kod örneği:
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
Bir aşağı yöntem darbelere IEnumerable<IEnumerable<T>>
bir halinde IEnumerable<T>
, komünizm gibi, her eleman (aptal biri bir dahi bir aynı haklara sahiptir) aynı şekilde davranış göstermiştir edilir.
var words = new [] { "a,b,c", "d,e", "f" };
var splitAndCombine = words.SelectMany(x => x.Split(','));
// returns { "a", "b", "c", "d", "e", "f" }
Sanırım anlamanın en iyi yolu bu.
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();
Çarpım Tablosu örneği.