C # 사전 하나의 키 많은 값
일부 데이터를 추가 데이터 저장소를 만들고 싶습니다.
첫 번째 아이디어는 많은 값을 가진 하나의 키가있는 사전을 만드는 것이기 때문에 일대 다 관계와 준비합니다.
사전에는 키 값이 1 개 뿐이라고 생각합니다.
이 정보를 어떻게합니까?
.net3.5 +부터를 사용하는 대신 Linq 네임 스페이스에서 Dictionary<IKey, List<IValue>>
사용할 수 있습니다 Lookup
.
// 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];
에서 MSDN :
조회는 사전과 유사합니다. 차이점은 사전은 키를 단일 값에 매핑하는 반면 조회는 키를 값 모음에 매핑하는 것입니다.
IEnumerable을 구현하는 개체에서 ToLookup을 호출하여 Lookup 인스턴스를 만들 수 있습니다.
관련 질문에 대한 이 답변 을 읽을 수도 있습니다 . 자세한 내용은 msdn을 참조하십시오 .
전체 예 :
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;
}
}
}
}
불변성에 대한 참조
기본적으로 Lookup은 불변이며에 액세스 internal
하는 데 반영이 필요합니다. 당신이 가변성이 필요하고 자신의 래퍼를 작성하지 않고 업데이트면, 당신은 사용할 수 있습니다. (이전 에서 사용할 수 있습니다 ) corefxlab (구 부분의 어떤 더 이상).MultiValueDictionary
MultiDictionary
Microsoft.Experimental.Collections
두 번째 일반 유형에 대한 목록을 사용할 수 있습니다. 예를 들어 한국어로 키가 고급 사전에 :
Dictionary<string, List<string>> myDict;
Microsoft는 NuGet을 통해 사용할 수있는 찾고있는 것과 정확히 일치하는 공식 시험판 버전 (MultiDictionary 함)을 여기에 추가했습니다. https://www.nuget.org/packages/Microsoft.Experimental.Collections/
사용법 및 자세한 내용은 공식 MSDN 블로그 게시물 ( http://blogs.msdn.com/b/dotnet/archive/2014/06/20/would-you-like-a-multidictionary.aspx)을 통해 확인할 수 있습니다.
저는이 패키지의 개발자입니다. 성능이나 기타 사항에 대한 질문이 있으면 여기 또는 MSDN을 통해 알려주십시오.
도움이되기를 바랍니다.
최신 정보
는 MultiValueDictionary
온 지금 corefxlab의 환매 특약 , 당신은에서 NuGet 패키지를 얻을 수있는 이 MyGet 피드.
사전의 값 유형은 목록 또는 여러 개체를 보유하는 다른 클래스 일 수 있습니다. 같은 것
Dictionary<int, List<string>>
정수로 키가 지정되고있는 경우 목록을 보유하는 사전의 경우.
값 유형을 선택할 때 주요 고려 사항은 사전을 사용할 대상입니다. 값에 대해 검색 또는 기타 작업을 수행해야하는 경우 원하는 작업을 수행하는 데 도움이되는 데이터 구조를 사용할 수 있습니다. -HashSet처럼.
이것을 사용하십시오 :
Dictionary<TKey, Tuple<TValue1, TValue2, TValue3, ...>>
당신은 사용할 수 있습니다 Dictionary<TKey, List<TValue>>
.
그러면 각 키가 값 목록 을 참조 할 수 있습니다.
목록 사전 (또는 다른 유형의 컬렉션)을 사용합니다. 예를 들면 다음과 같습니다.
var myDictionary = new Dictionary<string, IList<int>>();
myDictionary["My key"] = new List<int> {1, 2, 3, 4, 5};
컬렉션 (또는 다른 유형 / 클래스)이있는 사전을 값으로 수 있습니다. 이렇게하면 단일 키가 있고 컬렉션에 값을 저장합니다.
.NET 사전에는 키와 값에 대한 일대일 관계 만 있습니다. 그러나 슬픈 것은 무엇입니까?
나는 사전에 일대 다 관계를 이유를 생각할 수 없지만 하나가 있습니다.
키에 저장하려는 다양한 유형의 데이터가있는 경우에만의 클래스를 생성 할 경우 자신이 인 것입니다. 그런 다음 1 대 1이 1 개 이상의 데이터를 저장하는 값 클래스가 있습니다.
마이크로 소프트의 MultiValueDictionary 를 살펴보십시오 .
예제 코드 :
MultiValueDictionary<string, string> Parameters = new MultiValueDictionary<string, string>();
Parameters.Add("Malik", "Ali");
Parameters.Add("Malik", "Hamza");
Parameters.Add("Malik", "Danish");
//Parameters["Malik"] now contains the values Ali, Hamza, and Danish
이 동작을 달성하는 방법은 다음과 변화합니다.
관련된 것보다 솔루션 인 솔루션에 대한 답변을ILookup<TKey, TElement>
확인하십시오 .
public abstract class Lookup<TKey, TElement> : KeyedCollection<TKey, ICollection<TElement>>
{
protected override TKey GetKeyForItem(ICollection<TElement> item) =>
item
.Select(b => GetKeyForItem(b))
.Distinct()
.SingleOrDefault();
protected abstract TKey GetKeyForItem(TElement item);
public void Add(TElement item)
{
var key = GetKeyForItem(item);
if (Dictionary != null && Dictionary.TryGetValue(key, out var collection))
collection.Add(item);
else
Add(new List<TElement> { item });
}
public void Remove(TElement item)
{
var key = GetKeyForItem(item);
if (Dictionary != null && Dictionary.TryGetValue(key, out var collection))
{
collection.Remove(item);
if (collection.Count == 0)
Remove(key);
}
}
}
용법 :
public class Item
{
public string Key { get; }
public string Value { get; set; }
public Item(string key, string value = null) { Key = key; Value = value; }
}
public class Lookup : Lookup<string, Item>
{
protected override string GetKeyForItem(Item item) => item.Key;
}
static void Main(string[] args)
{
var toRem = new Item("1", "different");
var single = new Item("2", "single");
var lookup = new Lookup()
{
new Item("1", "hello"),
new Item("1", "hello2"),
new Item(""),
new Item("", "helloo"),
toRem,
single
};
lookup.Remove(toRem);
lookup.Remove(single);
}
참고 : 키는 변경이 불가능합니다 (또는 키 변경시 제거하고 다시 추가).
사용할 수도 있습니다.
List<KeyValuePair<string, string>> Mappings;
다음과 같은 값 삽입 프로세스를 자동화하는 매우 단순한 다중 사전을 만들 수 있습니다.
public class MultiDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>
{
public void Add(TKey key, TValue value)
{
if (TryGetValue(key, out List<TValue> valueList)) {
valueList.Add(value);
} else {
Add(key, new List<TValue> { value });
}
}
}
이렇게하면 Add
메서드 의 오버로드 된 버전이 생성 됩니다. 원래 항목을 사용하면이 항목에 대한 항목이 아직없는 경우 키 항목 목록을 삽입 할 수 있습니다. 이 버전에서는 어떤 경우에도 단일 항목을 삽입 할 수 있습니다.
참고 URL : https://stackoverflow.com/questions/2101069/c-sharp-dictionary-one-key-many-values
'ProgramingTip' 카테고리의 다른 글
변수가 한 노드 또는 다른 노드 같은지 확인하는 방법은 무엇입니까? (0) | 2020.11.26 |
---|---|
날짜 형식은 날짜 형식을 날짜 형식화하지 않습니다. (0) | 2020.11.26 |
BOOL을 삽입하는 Objective-C 사전 (0) | 2020.11.26 |
jquery를 사용하여 화면의 '높이'를 얻는 방법 (0) | 2020.11.26 |
Objective C에서 NSNumber 비교 (0) | 2020.11.26 |