Tính đến .net3.5 + thay vì sử dụng một Dictionary<IKey, List<IValue>>
bạn có thể sử dụng một Lookup
từ namespace LINQ:
// lookup Order by payment status (1:m)
// would need something like Dictionary<Boolean, IEnumerable<Order>> orderIdByIsPayed
ILookup<Boolean, Order> byPayment = orderList.ToLookup(o => o.IsPayed);
IEnumerable<Order> payedOrders = byPayment[false];
Từ msdn:
một Lookup giống như một từ điển. Sự khác biệt là một khóa bản đồ từ điển cho các giá trị đơn lẻ, trong khi đó, các khóa bản đồ Lookup để thu thập các giá trị .
Bạn có thể tạo phiên bản của Tìm kiếm bằng cách gọi ToLookup trên một đối tượng triển khai IEnumerable.
Bạn cũng có thể muốn đọc this answer đến related question. Để biết thêm thông tin, hãy tham khảo msdn.
Full dụ:
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqLookupSpike
{
class Program
{
static void Main(String[] args)
{
// init
var orderList = new List<Order>();
orderList.Add(new Order(1, 1, 2010, true));//(orderId, customerId, year, isPayed)
orderList.Add(new Order(2, 2, 2010, true));
orderList.Add(new Order(3, 1, 2010, true));
orderList.Add(new Order(4, 2, 2011, true));
orderList.Add(new Order(5, 2, 2011, false));
orderList.Add(new Order(6, 1, 2011, true));
orderList.Add(new Order(7, 3, 2012, false));
// lookup Order by its id (1:1, so usual dictionary is ok)
Dictionary<Int32, Order> orders = orderList.ToDictionary(o => o.OrderId, o => o);
// lookup Order by customer (1:n)
// would need something like Dictionary<Int32, IEnumerable<Order>> orderIdByCustomer
ILookup<Int32, Order> byCustomerId = orderList.ToLookup(o => o.CustomerId);
foreach (var customerOrders in byCustomerId)
{
Console.WriteLine("Customer {0} ordered:", customerOrders.Key);
foreach (var order in customerOrders)
{
Console.WriteLine(" Order {0} is payed: {1}", order.OrderId, order.IsPayed);
}
}
// the same using old fashioned Dictionary
Dictionary<Int32, List<Order>> orderIdByCustomer;
orderIdByCustomer = byCustomerId.ToDictionary(g => g.Key, g => g.ToList());
foreach (var customerOrders in orderIdByCustomer)
{
Console.WriteLine("Customer {0} ordered:", customerOrders.Key);
foreach (var order in customerOrders.Value)
{
Console.WriteLine(" Order {0} is payed: {1}", order.OrderId, order.IsPayed);
}
}
// lookup Order by payment status (1:m)
// would need something like Dictionary<Boolean, IEnumerable<Order>> orderIdByIsPayed
ILookup<Boolean, Order> byPayment = orderList.ToLookup(o => o.IsPayed);
IEnumerable<Order> payedOrders = byPayment[false];
foreach (var payedOrder in payedOrders)
{
Console.WriteLine("Order {0} from Customer {1} is not payed.", payedOrder.OrderId, payedOrder.CustomerId);
}
}
class Order
{
// key properties
public Int32 OrderId { get; private set; }
public Int32 CustomerId { get; private set; }
public Int32 Year { get; private set; }
public Boolean IsPayed { get; private set; }
// additional properties
// private List<OrderItem> _items;
public Order(Int32 orderId, Int32 customerId, Int32 year, Boolean isPayed)
{
OrderId = orderId;
CustomerId = customerId;
Year = year;
IsPayed = isPayed;
}
}
}
}
Ghi chú về tính bất biến
Theo mặc định, tra cứu là loại không thể thay đổi và truy cập vào internal
s sẽ bao gồm phản ánh. Nếu bạn cần sự biến đổi và không muốn viết trình bao bọc riêng, bạn có thể sử dụng MultiValueDictionary
(trước đây gọi là MultiDictionary
) từ corefxlab (trước đây là một phần của Microsoft.Experimental.Collections
không được cập nhật nữa).
tra cứu là không thay đổi, xin vui lòng chỉ này ra trong câu trả lời của bạn. – Shimmy
Khám phá [câu trả lời của tôi] (https://stackoverflow.com/a/45824919/75500). – Shimmy
@Shimmy được cập nhật theo yêu cầu – mbx