Từ điển đa giá trị


76

Làm cách nào để tạo Từ điển đa giá trị trong c #?

Ví dụ: Dictionary<T,T,T>trong đó chữ T đầu tiên là khóa và hai chữ còn lại là giá trị.

vì vậy điều này sẽ có thể: Dictionary<int,object,double>

Cảm ơn

Câu trả lời:


62

Chỉ cần tạo một Pair<TFirst, TSecond>loại và sử dụng nó làm giá trị của bạn.

Tôi có một ví dụ về một trong mã nguồn C # in Depth của tôi . Sao lại ở đây cho đơn giản:

using System;
using System.Collections.Generic;

public sealed class Pair<TFirst, TSecond>
    : IEquatable<Pair<TFirst, TSecond>>
{
    private readonly TFirst first;
    private readonly TSecond second;

    public Pair(TFirst first, TSecond second)
    {
        this.first = first;
        this.second = second;
    }

    public TFirst First
    {
        get { return first; }
    }

    public TSecond Second
    {
        get { return second; }
    }

    public bool Equals(Pair<TFirst, TSecond> other)
    {
        if (other == null)
        {
            return false;
        }
        return EqualityComparer<TFirst>.Default.Equals(this.First, other.First) &&
               EqualityComparer<TSecond>.Default.Equals(this.Second, other.Second);
    }

    public override bool Equals(object o)
    {
        return Equals(o as Pair<TFirst, TSecond>);
    }

    public override int GetHashCode()
    {
        return EqualityComparer<TFirst>.Default.GetHashCode(first) * 37 +
               EqualityComparer<TSecond>.Default.GetHashCode(second);
    }
}

2
Ưu điểm so với KeyValuePair thông thường là gì? Có một số loại phí khi sử dụng KeyValuePair không?
— tanascius

1
Chủ yếu đó là sự khác biệt về sự nhấn mạnh - trong khi KeyValuePair thực sự đóng gói một cặp giá trị, nó ngụ ý một loại mối quan hệ cụ thể giữa chúng ... điều này không.
— Jon Skeet

19
Điều này có giống với Tuple trong .Net 4.0 không?
— adam0101

2
@ adam0101: Cũng giống nhau thôi.
— Jon Skeet

4
@BasselAlkhateeb: Nếu bạn không thích việc có thể để có được các giá trị trở lại, sau đó có, mà mỹ nhân ...
— Jon Skeet

64

Nếu bạn đang cố gắng nhóm các giá trị lại với nhau, đây có thể là một cơ hội tuyệt vời để tạo một cấu trúc hoặc lớp đơn giản và sử dụng nó làm giá trị trong từ điển.

public struct MyValue
{
    public object Value1;
    public double Value2;
}

sau đó bạn có thể có từ điển của bạn

var dict = new Dictionary<int, MyValue>();

bạn thậm chí có thể tiến thêm một bước nữa và triển khai lớp từ điển của riêng mình để xử lý bất kỳ thao tác đặc biệt nào mà bạn cần. ví dụ: nếu bạn muốn có một phương thức Add chấp nhận một int, object và double

public class MyDictionary : Dictionary<int, MyValue>
{
    public void Add(int key, object value1, double value2)
    {
        MyValue val;
        val.Value1 = value1;
        val.Value2 = value2;
        this.Add(key, val);
    }
}

sau đó bạn có thể chỉ cần khởi tạo và thêm vào từ điển như vậy và bạn sẽ không phải lo lắng về việc tạo cấu trúc 'MyValue':

var dict = new MyDictionary();
dict.Add(1, new Object(), 2.22);

30
Dictionary<T1, Tuple<T2, T3>>

Chỉnh sửa: Xin lỗi - Tôi quên rằng bạn không tải được Tuples cho đến khi .NET 4.0 ra mắt. Ôi!


1
Tuples nằm trong .NET 4.0 BCL và nó không liên quan đến C # 4.0. Các tính năng của C # 4.0 không đề cập đến hỗ trợ tuple. Vui lòng sửa câu trả lời của bạn.
— Eriawan Kusumawardhono

Vấn đề với bộ tuple là các giá trị không được đặt tên.
— ProfK

2
Hơn nữa, các giá trị Tuple chỉ được đọc, điều này có thể ổn trong một số trường hợp, nhưng nên cân nhắc trước khi sử dụng chúng.
— Sebastian Werk

Thông tin rất tốt. Cho phép tôi mở rộng mã từ điển hiện có. Cảm ơn.
— Mike Malter

6

Tôi nghĩ rằng điều này là khá quá mức cần thiết đối với ngữ nghĩa từ điển, vì từ điển theo định nghĩa là một tập hợp các khóa và các giá trị tương ứng của nó, giống như cách chúng ta xem một cuốn sách từ điển ngôn ngữ có chứa một từ làm khóa và ý nghĩa mô tả của nó là giá trị.

Nhưng bạn có thể đại diện cho một từ điển có thể chứa tập hợp các giá trị, ví dụ:

Dictionary<String,List<Customer>>

Hoặc từ điển của một khóa và giá trị như một từ điển:

Dictionary<Customer,Dictionary<Order,OrderDetail>>

Sau đó, bạn sẽ có một từ điển có thể có nhiều giá trị.


1
Ngay sau khi bạn bắt đầu lồng các từ điển, mã của bạn bắt đầu trông giống như các mảng đa chiều.
— IAbstract

@IAbstract nó không giống nhau về ngữ nghĩa. Mảng nhiều chiều không quan tâm đến sự kết hợp của các khóa-giá trị. Ngoài ra Mảng đa chiều không quan tâm đến phần tử tối đa là hai (giống như từ điển phải có).
— Eriawan Kusumawardhono

@eriawan: Tôi không nghĩ rằng tôi đã rõ ràng :) ... giả sử giá trị int cho các khóa: myColl[0][1]... trông giống như một mảng đa chiều. Khi bạn bắt đầu lồng các bộ sưu tập, tôi tin rằng đã đến lúc đóng gói bộ sưu tập 'giá trị' một cách thích hợp.
— IAbstract

@IAbstract đó là một điểm tốt! Bây giờ tôi hiểu quan điểm của bạn trong bình luận cuối cùng của bạn. Tôi đồng ý rằng chúng ta nên đóng gói tập hợp giá trị đúng cách.
— Eriawan Kusumawardhono

5

Tôi không nghĩ rằng bạn có thể làm điều đó trực tiếp. Mặc dù vậy, bạn có thể tạo một lớp chứa cả của bạn objectvà doublevà đặt một trường hợp của nó vào từ điển.

class Pair
{
    object obj;
    double dbl;
}

Dictionary<int, Pair> = new Dictionary<int, Pair>();

2

Nếu các giá trị có liên quan với nhau, tại sao không đóng gói chúng trong một lớp và chỉ sử dụng Từ điển cũ đơn giản?


Sẽ dễ đọc hơn Pair và Tuple. First, Second, Item1, Item2 là gì?
— KornMuffin

1

Bạn mô tả một multimap.

Bạn có thể đặt giá trị thành đối tượng Danh sách, để lưu trữ nhiều hơn một giá trị (> 2 để có thể mở rộng).

Ghi đè đối tượng từ điển.


1

Tôi đã giải quyết bằng cách sử dụng:

Dictionary<short, string[]>

Như thế này

Dictionary<short, string[]> result = new Dictionary<short, string[]>();
result.Add(1,
           new string[] 
                    { 
                    "FirstString",
                    "Second"
                    }
                );
        }
return result;

1

Tôi biết đây là một chủ đề cũ, nhưng - vì nó không được đề cập nên hoạt động

  Dictionary<string, object> LookUp = new Dictionary<string, object>();
  LookUp.Add("bob", new { age = "23", height = "2.1m", weight = "110kg"});
  LookUp.Add("jasper", new { age = "33", height = "1.75m", weight = "90kg"});
  foreach(KeyValuePair<string, object> entry in LookUp )
  {
      object person = entry.Value;
      Console.WriteLine("Person name:" + entry.Key + " Age: "  + person.age);          
  }

0

Đây là cách triển khai một khóa duy nhất cho ánh xạ đa giá trị trong C # sử dụng loại khóa dựa trên tập hợp:

https://github.com/ColmBhandal/CsharpExtras/blob/master/CsharpExtras/Dictionary/MultiValueMapImpl.cs

Từ điển hoạt động giống như một từ điển thông thường từ loại khóa vào một tập hợp loại giá trị, nhưng cũng cung cấp chức năng để thêm trực tiếp một giá trị duy nhất của loại giá trị và trong nền xử lý việc tạo một tập hợp cơ bản và / hoặc thêm vào bộ đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.