คีย์ที่ซ้ำกันในพจนานุกรม. NET


256

มีคลาสพจนานุกรมในไลบรารีคลาสฐาน. NET ซึ่งอนุญาตให้ใช้คีย์ที่ซ้ำกันหรือไม่ ทางออกเดียวที่ฉันพบคือการสร้างตัวอย่างเช่นชั้นเรียน:

Dictionary<string, List<object>>

แต่มันค่อนข้างน่ารำคาญที่จะใช้งานจริง ใน Java ฉันเชื่อว่า MultiMap ทำสิ่งนี้ได้ แต่ไม่สามารถหา analog ใน. NET


3
คีย์ที่ซ้ำกันนี้เป็นอย่างไรค่าที่ซ้ำกัน (รายการ) ใช่ไหม
Shamim Hafiz

1
@ShamimHafiz ไม่ค่าไม่จำเป็นต้องซ้ำกัน หากคุณมีการซ้ำกันร้านค้า{ a, 1 }และ{ a, 2 }ในตารางแฮชที่เป็นกุญแจสำคัญทางเลือกหนึ่งคือการมีa { a, [1, 2] }
nawfal

1
ที่จริงฉันเชื่อว่าสิ่งที่ต้องการจริงๆที่นี่คือชุดสะสมที่แต่ละคีย์สามารถจับคู่กับค่าหนึ่งค่า ฉันคิดว่านิพจน์ "คีย์ซ้ำ" ไม่ได้สื่อสิ่งนี้
DavidRR

สำหรับการอ้างอิงในอนาคตคุณควรพิจารณาที่จะเก็บ 1 คีย์เพียงเพิ่มค่าลงไปแทนการเพิ่มคีย์เดิมซ้ำไปซ้ำมา
Ya Wang

หากทั้งคีย์และค่าเป็นสตริงจะมีNameValueCollection (ซึ่งสามารถเชื่อมโยงค่าสตริงหลายค่ากับแต่ละคีย์สตริง)
AnorZaken

คำตอบ:


228

หากคุณใช้. NET 3.5 ให้ใช้Lookupคลาส

แก้ไข: คุณมักสร้างโดยใช้Lookup Enumerable.ToLookupสิ่งนี้ถือว่าคุณไม่จำเป็นต้องเปลี่ยนแปลงในภายหลัง - แต่โดยทั่วไปฉันพบว่ามันดีพอ

หากวิธีนี้ไม่ได้ผลสำหรับคุณฉันไม่คิดว่าจะมีอะไรในกรอบที่จะช่วยได้และการใช้พจนานุกรมก็ดีเท่าที่จะได้รับ :(


ขอบคุณสำหรับ heads-up ในการค้นหา มันมีวิธีที่ยอดเยี่ยมในการแบ่งพาร์ติชัน (กลุ่ม) ผลลัพธ์จากเคียวรี linq ที่ไม่ได้เป็นเกณฑ์มาตรฐาน orderby
Robert Paulson

3
@ Josh: คุณใช้ Enumerable.ToLookup เพื่อสร้าง
Jon Skeet

29
คำเตือน : Lookupไม่ต่อเนื่องได้
SliverNinja - MSFT

1
เราควรเพิ่มรายการในการค้นหานั้นได้อย่างไร
moldovanu

171

คลาส List ใช้งานได้ดีทีเดียวสำหรับคอลเลกชันคีย์ / ค่าที่มีข้อมูลซ้ำซึ่งคุณต้องการวนซ้ำคอลเลกชัน ตัวอย่าง:

List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();

// add some values to the collection here

for (int i = 0;  i < list.Count;  i++)
{
    Print(list[i].Key, list[i].Value);
}

31
วิธีนี้ใช้งานได้จริง แต่การใช้งาน List ไม่มีความรู้เรื่องคีย์หรือค่าและไม่สามารถค้นหาคีย์ได้อย่างเหมาะสม
Spencer Rose

41

นี่เป็นวิธีหนึ่งในการทำสิ่งนี้ด้วย List <KeyValuePair <string, string>>

public class ListWithDuplicates : List<KeyValuePair<string, string>>
{
    public void Add(string key, string value)
    {
        var element = new KeyValuePair<string, string>(key, value);
        this.Add(element);
    }
}

var list = new ListWithDuplicates();
list.Add("k1", "v1");
list.Add("k1", "v2");
list.Add("k1", "v3");

foreach(var item in list)
{
    string x = string.format("{0}={1}, ", item.Key, item.Value);
}

เอาท์พุท k1 = v1, k1 = v2, k1 = v3


ใช้งานได้ดีในสถานการณ์ของฉันและใช้งานง่าย
user6121177

21

หากคุณกำลังใช้สตริงเป็นทั้งคีย์และค่าคุณสามารถใช้System.Collections.Specialized.NameValueCollectionซึ่งจะส่งกลับอาร์เรย์ของค่าสตริงผ่านเมธอด GetValues ​​(คีย์สตริง)


6
NameValueCollection ไม่อนุญาตให้ใช้หลายคีย์
Jenny O'Reilly

@ Jenny O'Reilly: แน่นอนว่าคุณสามารถเพิ่มคีย์ซ้ำได้
isHuman

พูดอย่างเคร่งครัด @ JennyO'Reilly ถูกต้องเป็นข้อสังเกตในหน้า MSDN ที่เชื่อมโยงอย่างชัดเจน: นี้ร้านค้าชั้นค่าสตริงหลายภายใต้คีย์เดียว
Ronald

มันจะอนุญาต แต่จะคืนค่าหลายค่าฉันลองใช้ดัชนีและคีย์
user6121177

18

ฉันเพิ่งเจอห้องสมุดPowerCollectionsซึ่งรวมถึงคลาสที่เรียกว่า MultiDictionary ฟังก์ชันนี้ห่อหุ้มฟังก์ชันการทำงานประเภทนี้อย่างเรียบร้อย


14

หมายเหตุสำคัญมากเกี่ยวกับการใช้การค้นหา:

คุณสามารถสร้างตัวอย่างของ a Lookup(TKey, TElement)โดยการเรียกToLookupใช้อ็อบเจกต์ที่ใช้งานIEnumerable(T)

Lookup(TKey, TElement)ไม่มีสร้างสาธารณะเพื่อสร้างตัวอย่างใหม่ของเป็น นอกจากนี้Lookup(TKey, TElement)วัตถุไม่เปลี่ยนรูปนั่นคือคุณไม่สามารถเพิ่มหรือลบองค์ประกอบหรือกุญแจจากLookup(TKey, TElement)วัตถุหลังจากที่มันถูกสร้างขึ้น

(จาก MSDN)

ฉันคิดว่านี่จะเป็นการปิดกั้นการแสดงสำหรับการใช้งานส่วนใหญ่


6
ฉันคิดว่ามีการใช้งานน้อยมากซึ่งนี่จะเป็นการหยุดการแสดง แต่แล้วฉันคิดว่าวัตถุที่เปลี่ยนไม่ได้นั้นยอดเยี่ยม
Joel Mueller

1
@ JoelMueller ฉันสามารถนึกถึงหลายกรณีที่นี่เป็นรายการโชว์ ไม่ต้องสร้างใหม่อีกครั้งพจนานุกรมเพื่อเพิ่มรายการไม่ได้เป็นวิธีการแก้ปัญหาที่มีประสิทธิภาพโดยเฉพาะอย่างยิ่ง ...
reirab

12

ฉันคิดว่าสิ่งที่ชอบที่List<KeyValuePair<object, object>>จะทำงาน


คุณค้นหาบางอย่างในรายการโดยใช้รหัสเป็นอย่างไร
Wayne Bloss

คุณต้องทำซ้ำมัน: แต่ฉันไม่ได้ตระหนักถึง LookUp-Class ของ. NET 3.5: บางทีนี่อาจมีประโยชน์มากกว่าสำหรับการค้นหาเนื้อหา
MADMap

2
@wizlib: วิธีเดียวคือการวนซ้ำรายการซึ่งแทบไม่มีประสิทธิภาพเท่ากับ hashing -1
petr k

@petrk ขึ้นอยู่กับว่าข้อมูลของคุณคืออะไร ฉันใช้การติดตั้งนี้เพราะฉันมีคีย์ที่ไม่ซ้ำกันน้อยมากและไม่ต้องการมีค่าใช้จ่ายในการชนกันของแฮช +1
Evan M

9

หากคุณใช้> =. NET 4 คุณสามารถใช้TupleClass:

// declaration
var list = new List<Tuple<string, List<object>>>();

// to add an item to the list
var item = Tuple<string, List<object>>("key", new List<object>);
list.Add(item);

// to iterate
foreach(var i in list)
{
    Console.WriteLine(i.Item1.ToString());
}

ดูเหมือนว่าList<KeyValuePair<key, value>>วิธีการแก้ปัญหาดังกล่าวข้างต้น ฉันผิดหรือเปล่า?
Nathan Goings

6

มันง่ายพอที่จะ "พจนานุกรมของคุณเอง" ในเวอร์ชันที่อนุญาตให้ใช้รายการ "คีย์ซ้ำ" นี่คือการดำเนินการที่เรียบง่ายอย่างคร่าวๆ คุณอาจต้องการที่จะต้องพิจารณาการเพิ่มการสนับสนุนสำหรับพื้นมากที่สุด (ถ้าไม่ทั้งหมด) IDictionary<T>บน

public class MultiMap<TKey,TValue>
{
    private readonly Dictionary<TKey,IList<TValue>> storage;

    public MultiMap()
    {
        storage = new Dictionary<TKey,IList<TValue>>();
    }

    public void Add(TKey key, TValue value)
    {
        if (!storage.ContainsKey(key)) storage.Add(key, new List<TValue>());
        storage[key].Add(value);
    }

    public IEnumerable<TKey> Keys
    {
        get { return storage.Keys; }
    }

    public bool ContainsKey(TKey key)
    {
        return storage.ContainsKey(key);
    }

    public IList<TValue> this[TKey key]
    {
        get
        {
            if (!storage.ContainsKey(key))
                throw new KeyNotFoundException(
                    string.Format(
                        "The given key {0} was not found in the collection.", key));
            return storage[key];
        }
    }
}

ตัวอย่างแบบย่อเกี่ยวกับวิธีใช้:

const string key = "supported_encodings";
var map = new MultiMap<string,Encoding>();
map.Add(key, Encoding.ASCII);
map.Add(key, Encoding.UTF8);
map.Add(key, Encoding.Unicode);

foreach (var existingKey in map.Keys)
{
    var values = map[existingKey];
    Console.WriteLine(string.Join(",", values));
}


3

NameValueCollection รองรับค่าสตริงหลายค่าภายใต้คีย์เดียว (ซึ่งก็คือสตริง) แต่เป็นเพียงตัวอย่างเดียวที่ฉันรู้

ฉันมักจะสร้างโครงสร้างที่คล้ายกับตัวอย่างในเมื่อคุณพบสถานการณ์ที่ฉันต้องการฟังก์ชั่นประเภทนั้น


3

เมื่อใช้List<KeyValuePair<string, object>>ตัวเลือกนี้คุณสามารถใช้ LINQ เพื่อทำการค้นหา:

List<KeyValuePair<string, object>> myList = new List<KeyValuePair<string, object>>();
//fill it here
var q = from a in myList Where a.Key.Equals("somevalue") Select a.Value
if(q.Count() > 0){ //you've got your value }

2
ใช่ แต่นั่นไม่ได้ทำให้เร็วขึ้น (ยังไม่แฮช)
Haukman

3

เนื่องจาก C # ใหม่ (ฉันเชื่อว่ามาจาก 7.0) คุณสามารถทำสิ่งนี้:

var duplicatedDictionaryExample = new List<(string Key, string Value)> { ("", "") ... }

และคุณใช้มันเป็นรายการมาตรฐาน แต่มีสองค่าชื่อสิ่งที่คุณต้องการ

foreach(var entry in duplicatedDictionaryExample)
{ 
    // do something with the values
    entry.Key;
    entry.Value;
}

2

คุณหมายถึงความสอดคล้องกันและไม่ซ้ำกันจริงหรือไม่ ไม่เช่นนั้น hashtable จะไม่สามารถทำงานได้

ความสอดคล้องกันหมายความว่าสองคีย์ที่แยกจากกันสามารถแฮชกับค่าที่เท่ากัน แต่คีย์ไม่เท่ากัน

ตัวอย่างเช่นสมมติว่าฟังก์ชันแฮชของ hashtable ของคุณเป็นเพียง hashval = key mod 3 ทั้งแผนที่ 1 และ 4 เป็น 1 แต่มีค่าต่างกัน นี่คือที่ความคิดของคุณของรายการเข้ามาเล่น

เมื่อคุณต้องการค้นหา 1 ค่านั้นจะถูกแฮชเป็น 1 รายการจะถูกข้ามไปจนกว่าจะพบ Key = 1

หากคุณอนุญาตให้ใส่คีย์ซ้ำคุณจะไม่สามารถแยกความแตกต่างของคีย์ที่แมปกับค่าใด


2
ตารางแฮชจะจัดการกับคีย์ที่เกิดขึ้นกับแฮชเป็นค่าเดียวกัน (ซึ่งเรียกว่าการชน) ฉันหมายถึงสถานการณ์ที่คุณต้องการแมปค่าหลายค่ากับคีย์ที่แน่นอนเดียวกัน

2

วิธีที่ฉันใช้เป็นเพียงแค่

Dictionary<string, List<string>>

ในแบบที่คุณมีคีย์เดียวถือรายการสตริง

ตัวอย่าง:

List<string> value = new List<string>();
if (dictionary.Contains(key)) {
     value = dictionary[key];
}
value.Add(newValue);

ดีและสะอาด
Jerry Nixon

นี่เป็นทางออกที่ดีในการจัดการกรณีใช้ของฉัน
พากย์ stylee

1

ฉันสะดุดข้ามโพสต์นี้เพื่อค้นหาคำตอบเดียวกันและไม่พบเลยดังนั้นฉันจึงยกตัวอย่างโซลูชันกระดูกเปลือยโดยใช้รายการพจนานุกรมแทนที่โอเปอเรเตอร์ [] เพื่อเพิ่มพจนานุกรมใหม่ลงในรายการเมื่อคนอื่น ๆ ทั้งหมดมี คีย์ที่กำหนด (ชุด) และส่งคืนรายการค่า (รับ)
มันน่าเกลียดและไม่มีประสิทธิภาพมันจะได้รับ / ตั้งค่าโดยคีย์เท่านั้นและจะส่งกลับรายการเสมอ แต่ทำงานได้:

 class DKD {
        List<Dictionary<string, string>> dictionaries;
        public DKD(){
            dictionaries = new List<Dictionary<string, string>>();}
        public object this[string key]{
             get{
                string temp;
                List<string> valueList = new List<string>();
                for (int i = 0; i < dictionaries.Count; i++){
                    dictionaries[i].TryGetValue(key, out temp);
                    if (temp == key){
                        valueList.Add(temp);}}
                return valueList;}
            set{
                for (int i = 0; i < dictionaries.Count; i++){
                    if (dictionaries[i].ContainsKey(key)){
                        continue;}
                    else{
                        dictionaries[i].Add(key,(string) value);
                        return;}}
                dictionaries.Add(new Dictionary<string, string>());
                dictionaries.Last()[key] =(string)value;
            }
        }
    }

1

ฉันเปลี่ยนคำตอบของ @Hector Correa เป็นส่วนขยายด้วยประเภททั่วไปและเพิ่ม TryGetValue แบบกำหนดเอง

  public static class ListWithDuplicateExtensions
  {
    public static void Add<TKey, TValue>(this List<KeyValuePair<TKey, TValue>> collection, TKey key, TValue value)
    {
      var element = new KeyValuePair<TKey, TValue>(key, value);
      collection.Add(element);
    }

    public static int TryGetValue<TKey, TValue>(this List<KeyValuePair<TKey, TValue>> collection, TKey key, out IEnumerable<TValue> values)
    {
      values = collection.Where(pair => pair.Key.Equals(key)).Select(pair => pair.Value);
      return values.Count();
    }
  }

0

นี่คือวิธีที่จะดึงพจนานุกรมที่เกิดขึ้นพร้อมกันฉันคิดว่านี่จะช่วยคุณได้:

public class HashMapDictionary<T1, T2> : System.Collections.IEnumerable
{
    private System.Collections.Concurrent.ConcurrentDictionary<T1, List<T2>> _keyValue = new System.Collections.Concurrent.ConcurrentDictionary<T1, List<T2>>();
    private System.Collections.Concurrent.ConcurrentDictionary<T2, List<T1>> _valueKey = new System.Collections.Concurrent.ConcurrentDictionary<T2, List<T1>>();

    public ICollection<T1> Keys
    {
        get
        {
            return _keyValue.Keys;
        }
    }

    public ICollection<T2> Values
    {
        get
        {
            return _valueKey.Keys;
        }
    }

    public int Count
    {
        get
        {
            return _keyValue.Count;
        }
    }

    public bool IsReadOnly
    {
        get
        {
            return false;
        }
    }

    public List<T2> this[T1 index]
    {
        get { return _keyValue[index]; }
        set { _keyValue[index] = value; }
    }

    public List<T1> this[T2 index]
    {
        get { return _valueKey[index]; }
        set { _valueKey[index] = value; }
    }

    public void Add(T1 key, T2 value)
    {
        lock (this)
        {
            if (!_keyValue.TryGetValue(key, out List<T2> result))
                _keyValue.TryAdd(key, new List<T2>() { value });
            else if (!result.Contains(value))
                result.Add(value);

            if (!_valueKey.TryGetValue(value, out List<T1> result2))
                _valueKey.TryAdd(value, new List<T1>() { key });
            else if (!result2.Contains(key))
                result2.Add(key);
        }
    }

    public bool TryGetValues(T1 key, out List<T2> value)
    {
        return _keyValue.TryGetValue(key, out value);
    }

    public bool TryGetKeys(T2 value, out List<T1> key)
    {
        return _valueKey.TryGetValue(value, out key);
    }

    public bool ContainsKey(T1 key)
    {
        return _keyValue.ContainsKey(key);
    }

    public bool ContainsValue(T2 value)
    {
        return _valueKey.ContainsKey(value);
    }

    public void Remove(T1 key)
    {
        lock (this)
        {
            if (_keyValue.TryRemove(key, out List<T2> values))
            {
                foreach (var item in values)
                {
                    var remove2 = _valueKey.TryRemove(item, out List<T1> keys);
                }
            }
        }
    }

    public void Remove(T2 value)
    {
        lock (this)
        {
            if (_valueKey.TryRemove(value, out List<T1> keys))
            {
                foreach (var item in keys)
                {
                    var remove2 = _keyValue.TryRemove(item, out List<T2> values);
                }
            }
        }
    }

    public void Clear()
    {
        _keyValue.Clear();
        _valueKey.Clear();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return _keyValue.GetEnumerator();
    }
}

ตัวอย่าง:

public class TestA
{
    public int MyProperty { get; set; }
}

public class TestB
{
    public int MyProperty { get; set; }
}

            HashMapDictionary<TestA, TestB> hashMapDictionary = new HashMapDictionary<TestA, TestB>();

            var a = new TestA() { MyProperty = 9999 };
            var b = new TestB() { MyProperty = 60 };
            var b2 = new TestB() { MyProperty = 5 };
            hashMapDictionary.Add(a, b);
            hashMapDictionary.Add(a, b2);
            hashMapDictionary.TryGetValues(a, out List<TestB> result);
            foreach (var item in result)
            {
                //do something
            }

0

ฉันใช้คลาสง่าย ๆ นี้:

public class ListMap<T,V> : List<KeyValuePair<T, V>>
{
    public void Add(T key, V value) {
        Add(new KeyValuePair<T, V>(key, value));
    }

    public List<V> Get(T key) {
        return FindAll(p => p.Key.Equals(key)).ConvertAll(p=> p.Value);
    }
}

การใช้งาน:

var fruits = new ListMap<int, string>();
fruits.Add(1, "apple");
fruits.Add(1, "orange");
var c = fruits.Get(1).Count; //c = 2;

0

คุณสามารถสร้าง wrapper พจนานุกรมของคุณเองซึ่งคล้ายกับสิ่งนี้เนื่องจากโบนัสสนับสนุนค่า null เป็นคีย์:

/// <summary>
/// Dictionary which supports duplicates and null entries
/// </summary>
/// <typeparam name="TKey">Type of key</typeparam>
/// <typeparam name="TValue">Type of items</typeparam>
public class OpenDictionary<TKey, TValue>
{
    private readonly Lazy<List<TValue>> _nullStorage = new Lazy<List<TValue>>(
        () => new List<TValue>());

    private readonly Dictionary<TKey, List<TValue>> _innerDictionary =
        new Dictionary<TKey, List<TValue>>();

    /// <summary>
    /// Get all entries
    /// </summary>
    public IEnumerable<TValue> Values =>
        _innerDictionary.Values
            .SelectMany(x => x)
            .Concat(_nullStorage.Value);

    /// <summary>
    /// Add an item
    /// </summary>
    public OpenDictionary<TKey, TValue> Add(TKey key, TValue item)
    {
        if (ReferenceEquals(key, null))
            _nullStorage.Value.Add(item);
        else
        {
            if (!_innerDictionary.ContainsKey(key))
                _innerDictionary.Add(key, new List<TValue>());

            _innerDictionary[key].Add(item);
        }

        return this;
    }

    /// <summary>
    /// Remove an entry by key
    /// </summary>
    public OpenDictionary<TKey, TValue> RemoveEntryByKey(TKey key, TValue entry)
    {
        if (ReferenceEquals(key, null))
        {
            int targetIdx = _nullStorage.Value.FindIndex(x => x.Equals(entry));
            if (targetIdx < 0)
                return this;

            _nullStorage.Value.RemoveAt(targetIdx);
        }
        else
        {
            if (!_innerDictionary.ContainsKey(key))
                return this;

            List<TValue> targetChain = _innerDictionary[key];
            if (targetChain.Count == 0)
                return this;

            int targetIdx = targetChain.FindIndex(x => x.Equals(entry));
            if (targetIdx < 0)
                return this;

            targetChain.RemoveAt(targetIdx);
        }

        return this;
    }

    /// <summary>
    /// Remove all entries by key
    /// </summary>
    public OpenDictionary<TKey, TValue> RemoveAllEntriesByKey(TKey key)
    {
        if (ReferenceEquals(key, null))
        {
            if (_nullStorage.IsValueCreated)
                _nullStorage.Value.Clear();
        }       
        else
        {
            if (_innerDictionary.ContainsKey(key))
                _innerDictionary[key].Clear();
        }

        return this;
    }

    /// <summary>
    /// Try get entries by key
    /// </summary>
    public bool TryGetEntries(TKey key, out IReadOnlyList<TValue> entries)
    {
        entries = null;

        if (ReferenceEquals(key, null))
        {
            if (_nullStorage.IsValueCreated)
            {
                entries = _nullStorage.Value;
                return true;
            }
            else return false;
        }
        else
        {
            if (_innerDictionary.ContainsKey(key))
            {
                entries = _innerDictionary[key];
                return true;
            }
            else return false;
        }
    }
}

ตัวอย่างการใช้งาน:

var dictionary = new OpenDictionary<string, int>();
dictionary.Add("1", 1); 
// The next line won't throw an exception; 
dictionary.Add("1", 2);

dictionary.TryGetEntries("1", out List<int> result); 
// result is { 1, 2 }

dictionary.Add(null, 42);
dictionary.Add(null, 24);
dictionary.TryGetEntries(null, out List<int> result); 
// result is { 42, 24 }

คุณสามารถอธิบายเกี่ยวกับสิ่งที่รหัสของคุณทำอย่างไรตอบคำถามและวิธีการใช้งานตัวอย่าง
Enigmativity

@Enigmativity มันทำในสิ่งที่ถูกถามคำถามคือการแนะนำพจนานุกรมที่รองรับการซ้ำดังนั้นฉันจึงเสนอให้สร้าง wrapper รอบ ๆ . net dictionary ซึ่งจะรองรับฟังก์ชั่นนี้และเป็นตัวอย่างที่สร้าง wrapper ดังกล่าวเป็นโบนัสที่มันสามารถทำได้ จัดการ null เป็นกุญแจสำคัญ (แม้ว่าจะเป็นการปฏิบัติที่ไม่ดีแน่นอน) การใช้งานค่อนข้างง่าย: var dictionary = new OpenDictionary<string, int>(); dictionary.Add("1", 1); // The next line won't throw an exception; dictionary.Add("1", 2); dictionary.TryGetEntries("1", out List<int> result); // result is { 1, 2 }
Alexander Tolstikov

คุณสามารถเพิ่มรายละเอียดในคำตอบของคุณ?
Enigmativity

@Enigmativity ถ้าคุณหมายถึงคำตอบเดิมแน่นอน
Alexander Tolstikov

-1

คุณสามารถกำหนดวิธีการสร้างคีย์สตริงแบบผสมได้ทุกที่ที่คุณต้องการใช้พจนานุกรมคุณต้องใช้วิธีนี้ในการสร้างคีย์ของคุณเช่น:

private string keyBuilder(int key1, int key2)
{
    return string.Format("{0}/{1}", key1, key2);
}

สำหรับการใช้งาน:

myDict.ContainsKey(keyBuilder(key1, key2))

-3

คีย์ที่ซ้ำกันทำให้สัญญาทั้งหมดของพจนานุกรมเสียหาย ในพจนานุกรมแต่ละคีย์จะไม่ซ้ำกันและแมปกับค่าเดียว หากคุณต้องการเชื่อมโยงวัตถุกับจำนวนเพิ่มเติมของวัตถุใด ๆ ทางออกที่ดีที่สุดอาจเป็นสิ่งที่คล้ายกับชุดข้อมูล (ในสำนวนทั่วไปในตาราง) ใส่กุญแจของคุณในหนึ่งคอลัมน์และค่าของคุณในอื่น ๆ สิ่งนี้ช้ากว่าพจนานุกรมอย่างมาก แต่นั่นคือการสูญเสียความสามารถในการแฮชวัตถุสำคัญของคุณ


5
จุดรวมของการใช้พจนานุกรมสำหรับการเพิ่มประสิทธิภาพนั้นไม่ใช่หรือ ดูเหมือนว่าการใช้ชุดข้อมูลจะไม่ดีไปกว่า List <KeyValuePair <T, U >>
Doug

-4

นอกจากนี้ยังเป็นไปได้:

Dictionary<string, string[]> previousAnswers = null;

ด้วยวิธีนี้เราสามารถมีกุญแจที่ไม่ซ้ำกัน หวังว่านี่จะเป็นประโยชน์สำหรับคุณ


OP ขอพจนานุกรมที่อนุญาตให้ใช้คีย์ซ้ำกัน
Skaparate

-10

คุณสามารถเพิ่มคีย์เดียวกันโดยใช้ตัวพิมพ์เล็กและตัวอักษรต่าง ๆ เช่น:

key1
Key1
KEY1
KeY1
kEy1
keY1

ฉันรู้ว่าเป็นคำตอบที่หลอก ๆ แต่ก็ใช้ได้กับฉัน


4
ไม่มันไม่ได้ผลสำหรับคุณ พจนานุกรมอนุญาตให้ค้นหาได้อย่างรวดเร็ว - จัดเป็นO (1) - โดยคีย์คุณจะสูญเสียว่าเมื่อคุณเพิ่มหลายคีย์ที่ใส่ซองที่แตกต่างกันเพราะคุณจะเรียกคืนได้อย่างไร ลองชุดตัวพิมพ์ใหญ่ / เล็กทุกตัวหรือไม่ ไม่ว่าคุณจะทำมันอย่างไรประสิทธิภาพจะไม่เป็นไปตามปกติการค้นหาพจนานุกรมเดียว นอกจากนี้ยังมีข้อบกพร่องอื่น ๆ ที่ชัดเจนกว่าเช่นข้อ จำกัด ของค่าต่อคีย์ขึ้นอยู่กับจำนวนของอักขระที่เพิ่มได้ในคีย์
Eugene Beresovsky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.