সি # তে দ্বি-দ্বি / দ্বিদ্বিতীয় অভিধান


90

আমি অভিধানে শব্দগুলি নিম্নলিখিত উপায়ে সংরক্ষণ করতে চাই:

আমি শব্দ দ্বারা শব্দ কোড পেতে পারি: dict["SomeWord"]-> 123এবং শব্দ কোড দ্বারা শব্দ পেতে: dict[123]->"SomeWord"

এটা কি সত্যি? অবশ্যই এটির একটি উপায় দুটি অভিধান: Dictionary<string,int>এবং Dictionary<int,string>তবে কি অন্য উপায় আছে?


4
(NET 4 হিসাবে) ডেটা-টাইপের কোনও মান নেই যা ও (1) উভয় ভাবে অ্যাক্সেস সরবরাহ করে ...

এছাড়াও নয় যে দ্বিপাক্ষিক-মানচিত্র (কীওয়ার্ড?) অতিরিক্ত বিধি-নিষেধ আরোপ করে, যদি না একাধিক দ্বি-

উত্তর:


110

আমি একটি ক্লাসের কয়েকটি দ্রুত লিখেছি যা আপনাকে যা করতে চায় তা করতে দেয়। আপনার সম্ভবত এটি আরও বৈশিষ্ট্য সহ প্রসারিত করার প্রয়োজন হবে তবে এটি একটি ভাল সূচনা পয়েন্ট।

কোডটির ব্যবহার দেখে মনে হচ্ছে:

var map = new Map<int, string>();

map.Add(42, "Hello");

Console.WriteLine(map.Forward[42]);
// Outputs "Hello"

Console.WriteLine(map.Reverse["Hello"]);
//Outputs 42

সংজ্ঞাটি এখানে:

public class Map<T1, T2>
{
    private Dictionary<T1, T2> _forward = new Dictionary<T1, T2>();
    private Dictionary<T2, T1> _reverse = new Dictionary<T2, T1>();

    public Map()
    {
        this.Forward = new Indexer<T1, T2>(_forward);
        this.Reverse = new Indexer<T2, T1>(_reverse);
    }

    public class Indexer<T3, T4>
    {
        private Dictionary<T3, T4> _dictionary;
        public Indexer(Dictionary<T3, T4> dictionary)
        {
            _dictionary = dictionary;
        }
        public T4 this[T3 index]
        {
            get { return _dictionary[index]; }
            set { _dictionary[index] = value; }
        }
    }

    public void Add(T1 t1, T2 t2)
    {
        _forward.Add(t1, t2);
        _reverse.Add(t2, t1);
    }

    public Indexer<T1, T2> Forward { get; private set; }
    public Indexer<T2, T1> Reverse { get; private set; }
}

4
@ পেড্রো 7777 - এটি এখন করে। ;-)
শত্রুতা

4
@ পেড্রো 7777 - আমার ক্লাসটি নতুন "মানচিত্র" সমাধান হ'ল পরামর্শ দিয়ে আমি কেবল বোকা হয়ে যাচ্ছিলাম।
igগিরিভিটি

12
এটি ব্যতিক্রমগুলিতে শ্রেণীর আক্রমণকারীগুলি বজায় রাখে না। _forward.Addসফল হওয়া এবং _reverse.Addব্যর্থ হওয়া আপনার পক্ষে আংশিক যুক্ত জুড়ি রেখে চলেছে possible

4
@ এইচভিডি - যেমনটি আমি বলেছিলাম - এটি দ্রুত একসাথে ক্লাস করা।
Enigmativity

4
@ এএএ এটি অভিধানের নিজস্বটি Forward(যা রয়েছে private set;) এটি সংশোধন করছে না, তবে এটি অভিধানের নিকটবর্তী সূচক শ্রেণীর সূচক সম্পত্তি থেকে সেই অভিধানের মানটি সংশোধন করছে। public T4 this[T3 index] { get { return _dictionary[index]; } set { _dictionary[index] = value; } }সুতরাং এটি ফরোয়ার্ড / বিপরীত চেহারা বিরতি।
জেরোইন ভ্যান ল্যাঞ্জেন

27

আফসোস, আপনার দুটি দিকনির্দেশক প্রয়োজন, প্রতিটি দিকের জন্য একটি। তবে, আপনি সহজেই লিনকিউ ব্যবহার করে বিপরীত অভিধানটি পেতে পারেন:

Dictionary<T1, T2> dict = new Dictionary<T1, T2>();
Dictionary<T2, T1> dictInverse = dict.ToDictionary((i) => i.Value, (i) => i.Key);

11

প্রারম্ভিককরণ এবং সমন্বিত পদ্ধতি যুক্ত করে এনিগিটিভিটি কোডে প্রসারিত।

public class Map<T1, T2> : IEnumerable<KeyValuePair<T1, T2>>
{
    private readonly Dictionary<T1, T2> _forward = new Dictionary<T1, T2>();
    private readonly Dictionary<T2, T1> _reverse = new Dictionary<T2, T1>();

    public Map()
    {
        Forward = new Indexer<T1, T2>(_forward);
        Reverse = new Indexer<T2, T1>(_reverse);
    }

    public Indexer<T1, T2> Forward { get; private set; }
    public Indexer<T2, T1> Reverse { get; private set; }

    public void Add(T1 t1, T2 t2)
    {
        _forward.Add(t1, t2);
        _reverse.Add(t2, t1);
    }

    public void Remove(T1 t1)
    {
        T2 revKey = Forward[t1];
        _forward.Remove(t1);
        _reverse.Remove(revKey);
    }
    
    public void Remove(T2 t2)
    {
        T1 forwardKey = Reverse[t2];
        _reverse.Remove(t2);
        _forward.Remove(forwardKey);
    }

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

    public IEnumerator<KeyValuePair<T1, T2>> GetEnumerator()
    {
        return _forward.GetEnumerator();
    }

    public class Indexer<T3, T4>
    {
        private readonly Dictionary<T3, T4> _dictionary;

        public Indexer(Dictionary<T3, T4> dictionary)
        {
            _dictionary = dictionary;
        }

        public T4 this[T3 index]
        {
            get { return _dictionary[index]; }
            set { _dictionary[index] = value; }
        }

        public bool Contains(T3 key)
        {
            return _dictionary.ContainsKey(key);
        }
    }
}

এখানে একটি ব্যবহারের কেস রয়েছে, বৈধ বন্ধনী পরীক্ষা করুন

public static class ValidParenthesisExt
{
    private static readonly Map<char, char>
        _parenthesis = new Map<char, char>
        {
            {'(', ')'},
            {'{', '}'},
            {'[', ']'}
        };

    public static bool IsValidParenthesis(this string input)
    {
        var stack = new Stack<char>();
        foreach (var c in input)
        {
            if (_parenthesis.Forward.Contains(c))
                stack.Push(c);
            else
            {
                if (stack.Count == 0) return false;
                if (_parenthesis.Reverse[c] != stack.Pop())
                    return false;
            }
        }
        return stack.Count == 0;
    }
}

7

আপনি দুটি অভিধান ব্যবহার করতে পারেন, যেমন অন্যরা বলেছেন, তবে এটিও নোট করুন যে যদি উভয় TKeyএবং TValueএকই ধরণের হয় (এবং তাদের রানটাইম মান ডোমেনগুলি বিচ্ছিন্ন বলে জানা যায়) তবে আপনি কেবল প্রতিটি কীটির জন্য দুটি এন্ট্রি তৈরি করে একই অভিধানটি ব্যবহার করতে পারেন / মান জুটি:

dict["SomeWord"]= "123" এবং dict["123"]="SomeWord"

উভয় প্রকারের অনুসন্ধানের জন্য এই পদ্ধতিতে একটি একক অভিধান ব্যবহার করা যেতে পারে।


4
হ্যাঁ, এই পদ্ধতির প্রশ্নটিতে স্বীকৃতি দেওয়া হয়েছিল :)

4
এটি "কী" এবং "মান" উভয় ক্ষেত্রে একই মানের সম্ভাবনাটিকে উপেক্ষা করে। তাহলে এটি এই সমাধানে বিরোধ করবে।
ব্যবহারকারী 1028741

4
@ ব্যবহারকারী 1028741 রাজি হয়েছে, যদিও উদাহরণ থেকে দেখা যায় যে তারা "ভিন্ন ধরণের" একই ধরণের "নয়" বোঝায়
হ্যাচ

এর ফলে ভবিষ্যতে অপ্রত্যাশিত ফলাফল হতে পারে তারপরে কোড রিফ্যাক্টরিংয়ের মধ্য দিয়ে যায়। যেমন তারপরে বাম এবং ডান দিকগুলি ওভারল্যাপ হতে শুরু করে। এটি পারফরম্যান্সে কিছুই যোগ করে না।
ভিনিগাস

6

হ্যাক কী, আমি আমার সংস্করণটি মিশ্রণে ফেলে দেব:

public class BijectiveDictionary<TKey, TValue> 
{
    private EqualityComparer<TKey> _keyComparer;
    private Dictionary<TKey, ISet<TValue>> _forwardLookup;
    private EqualityComparer<TValue> _valueComparer;
    private Dictionary<TValue, ISet<TKey>> _reverseLookup;             

    public BijectiveDictionary()
        : this(EqualityComparer<TKey>.Default, EqualityComparer<TValue>.Default)
    {
    }

    public BijectiveDictionary(EqualityComparer<TKey> keyComparer, EqualityComparer<TValue> valueComparer)
        : this(0, EqualityComparer<TKey>.Default, EqualityComparer<TValue>.Default)
    {
    }

    public BijectiveDictionary(int capacity, EqualityComparer<TKey> keyComparer, EqualityComparer<TValue> valueComparer)
    {
        _keyComparer = keyComparer;
        _forwardLookup = new Dictionary<TKey, ISet<TValue>>(capacity, keyComparer);            
        _valueComparer = valueComparer;
        _reverseLookup = new Dictionary<TValue, ISet<TKey>>(capacity, valueComparer);            
    }

    public void Add(TKey key, TValue value)
    {
        AddForward(key, value);
        AddReverse(key, value);
    }

    public void AddForward(TKey key, TValue value)
    {
        ISet<TValue> values;
        if (!_forwardLookup.TryGetValue(key, out values))
        {
            values = new HashSet<TValue>(_valueComparer);
            _forwardLookup.Add(key, values);
        }
        values.Add(value);
    }

    public void AddReverse(TKey key, TValue value) 
    {
        ISet<TKey> keys;
        if (!_reverseLookup.TryGetValue(value, out keys))
        {
            keys = new HashSet<TKey>(_keyComparer);
            _reverseLookup.Add(value, keys);
        }
        keys.Add(key);
    }

    public bool TryGetReverse(TValue value, out ISet<TKey> keys)
    {
        return _reverseLookup.TryGetValue(value, out keys);
    }

    public ISet<TKey> GetReverse(TValue value)
    {
        ISet<TKey> keys;
        TryGetReverse(value, out keys);
        return keys;
    }

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

    public bool TryGetForward(TKey key, out ISet<TValue> values)
    {
        return _forwardLookup.TryGetValue(key, out values);
    }

    public ISet<TValue> GetForward(TKey key)
    {
        ISet<TValue> values;
        TryGetForward(key, out values);
        return values;
    }

    public bool ContainsReverse(TValue value)
    {
        return _reverseLookup.ContainsKey(value);
    }

    public void Clear()
    {
        _forwardLookup.Clear();
        _reverseLookup.Clear();
    }
}

এটিতে কিছু ডেটা যুক্ত করুন:

var lookup = new BijectiveDictionary<int, int>();

lookup.Add(1, 2);
lookup.Add(1, 3);
lookup.Add(1, 4);
lookup.Add(1, 5);

lookup.Add(6, 2);
lookup.Add(6, 8);
lookup.Add(6, 9);
lookup.Add(6, 10);

এবং তারপরে দেখুন:

lookup[2] --> 1, 6
lookup[3] --> 1
lookup[8] --> 6

আমি এটি পছন্দ করি যে এটি 1: এন
সেবাস্তিয়ান

@ সেবাস্তিয়ান, আপনি মূল সংখ্যার <কীভ্যালু পেয়ার <টি কে, টিভিয়াল >> যোগ করতে পারেন।
ওস্ততি

4

আপনি এই এক্সটেনশন পদ্ধতিটি ব্যবহার করতে পারেন, যদিও এটি গণনা ব্যবহার করে, এবং এটি বড় ডেটা সেটগুলির জন্য পারফরম্যান্স নাও হতে পারে। আপনি যদি দক্ষতা সম্পর্কে চিন্তিত হন তবে আপনার দুটি অভিধান দরকার। আপনি যদি দুটি অভিধানকে একটি শ্রেণিতে গুটিয়ে রাখতে চান তবে এই প্রশ্নের গৃহীত উত্তরটি দেখুন: সি # তে দ্বিপাক্ষিক 1 থেকে 1 অভিধান

public static class IDictionaryExtensions
{
    public static TKey FindKeyByValue<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TValue value)
    {
        if (dictionary == null)
            throw new ArgumentNullException("dictionary");

        foreach (KeyValuePair<TKey, TValue> pair in dictionary)
            if (value.Equals(pair.Value)) return pair.Key;

        throw new Exception("the value is not found in the dictionary");
    }
}

8
যদিও এটি একটি দ্বিদ্বৈতশত অভিধান, মানটি আনা হচ্ছে একটি O (n) ক্রিয়া যেখানে এটি O (1) অপারেশন হওয়া উচিত। এটি ছোট ডেটা সেটগুলির জন্য গুরুত্বপূর্ণ নয়, তবে বড়দের সাথে কাজ করার সময় পারফরম্যান্সের সমস্যা তৈরি করতে পারে। স্থানের উপরে পারফরম্যান্সের সেরা উত্তরটি হ'ল বিপরীত ডেটা সহ দুটি অভিধান ব্যবহার করা।
টম

@ টোমা আমি টমের সাথে সম্পূর্ণরূপে সম্মতি জানাই, আপনার একমাত্র দৃষ্টিকোণ অভিধানের প্রয়োজন যেখানে আপনার 100K, 1 এম + এন্ট্রি থাকে, কোনও কম স্ক্যান করা কার্যকরভাবে এটি একটি নিওপ হয়।
ক্রিস মেরিসিক

আমি আমার পরিস্থিতিতে (ছোট ডিক্ট আকার) এর জন্য এই সমাধানটি পছন্দ করি কারণ আমি এখনও সংগ্রহের আরম্ভকারী ব্যবহার করতে পারি। মানচিত্রের উত্তর <ক, বি> গৃহীত উত্তরে আমি মনে করি না যে সংগ্রহের সূচনাযাত্রায় ব্যবহার করা যেতে পারে।
সিভেরটেক্স

@ ক্রিসমারিসিক, এটি প্রচার করার মতো একটি অদ্ভুত বিষয় বলে মনে হচ্ছে। যদি এই চেহারাটিকে শক্ত লুপে ডাকা হয়, আমি বাজি ধরছি, আপনি <500 এন্ট্রি সহও ব্যথা অনুভব করবেন। এটি তুলনা পরীক্ষার ব্যয়ের উপরও নির্ভর করে। আমি মনে করি না যে আপনার মন্তব্যের মতো পরিষ্কার বক্তব্যগুলি সহায়ক।
লি ক্যাম্পবেল

@ লাইক্যাম্পবেল আমার ঝাড়ু বিবৃতিগুলি পরিমাপযোগ্য এবং প্রোফাইলযুক্ত বাস্তবতার মতো বাস্তব বাস্তবতার অভিজ্ঞতার ভিত্তিতে। যদি আপনি অভিধানের কী হিসাবে কিছু জটিল প্রকারটি ব্যবহার করতে চান তবে এটি আমার সমস্যা নয়।
ক্রিস মেরিসিক

1

অভিধান

এখানে প্রতিটি উত্তরে আমি কী পছন্দ করেছি তার একটি সংমিশ্রণ এখানে দেওয়া হল। এটি প্রয়োগ করে IEnumerableযাতে এটি সংগ্রহের আরম্ভকারী ব্যবহার করতে পারে, যেমন আপনি উদাহরণটিতে দেখতে পারেন।

ব্যবহারের সীমাবদ্ধতা:

  • আপনি বিভিন্ন ডেটাটাইপ ব্যবহার করছেন। (যেমন, )T1T2

কোড:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        Bictionary<string, int> bictionary = 
            new Bictionary<string,int>() {
                { "a",1 }, 
                { "b",2 }, 
                { "c",3 } 
            };

        // test forward lookup
        Console.WriteLine(bictionary["b"]);
        // test forward lookup error
        //Console.WriteLine(bictionary["d"]);
        // test reverse lookup
        Console.WriteLine(bictionary[3]); 
        // test reverse lookup error (throws same error as forward lookup does)
        Console.WriteLine(bictionary[4]); 
    }
}

public class Bictionary<T1, T2> : Dictionary<T1, T2>
{
    public T1 this[T2 index]
    {
        get
        {
            if(!this.Any(x => x.Value.Equals(index)))
               throw new System.Collections.Generic.KeyNotFoundException();
            return this.First(x => x.Value.Equals(index)).Key;
        }
    }
}

ফিডল:

https://dotnetfiddle.net/mTNEuw


খুব মার্জিত সমাধান! আপনি কি এর সাহস আরও কিছুটা ব্যাখ্যা করতে পারেন? আমি কি ঠিক বলেছি যে Bictionary<string, string>সমস্ত স্ট্রিং অনন্য হলেও আপনি একটি তৈরি করতে পারবেন না ?
মার্কাস ম্যাঙ্গেলসডর্ফ

@ মেরলিন ২০০1, এটি সঠিক। আরও স্পষ্টভাবে, আপনি এটির সাথে ফরোয়ার্ড লুকআপ করতে পারবেন না। কীভাবে এটি পরাভূত করতে হবে তা নিয়ে আমাকে ভাবতে হবে। এটি সংকলন করে তবে সর্বদা বিপরীত সূচকটি প্রথমে সন্ধান করে T1 == T2, সুতরাং সামনের দিকে অনুসন্ধান ব্যর্থ হয়। তদুপরি, আমি ডিফল্ট সূচকটিকে ওভাররাইড করতে পারি না কারণ এরপরে লুকিং কলগুলি অস্পষ্ট হবে। আমি এই সীমাবদ্ধতাটি যুক্ত করেছি এবং পূর্ববর্তীটিকে মুছে ফেলেছি কারণ মানগুলির T1মানগুলির সাথে ওভারল্যাপ হতে পারে T2
টুডমো

10
বিপরীতে একটি দুর্দান্ত গুরুতর পারফরম্যান্স সমস্যা আছে; ও (এন) পারফরম্যান্স হিট করে অভিধানটি দুটিবার অনুসন্ধান করা হয়েছে; দ্বিতীয় অভিধানটি ব্যবহার করা আরও দ্রুত হবে এবং ধরণের সীমাবদ্ধতাটি সরিয়ে ফেলবে।
স্টিভ কুপার

@ স্টিভকুপার, সম্ভবত আমি এটিকে মুড়ে ফেলা tryএবং ব্যতিক্রমগুলিকে রূপান্তর করে পারফরম্যান্সের হিট থেকে মুক্তি পেতে পারি KeyNotFoundExceptions
টডডমো

4
@ টডডমো আপনি এইভাবে গতি দ্বিগুণ করতে সক্ষম হতে পারেন। বৃহত্তর সমস্যা হ'ল উভয় .প্রথম এবং .এক সময়ে একটি করে আইটেম অনুসন্ধান করুন, প্রতিটি পরীক্ষার চেষ্টা করুন। সুতরাং 1,000,000 আইটেমের তালিকাটি পরীক্ষা করতে 1-উপাদান তালিকার চেয়ে 1000,000 বার বেশি সময় লাগে takes অভিধানগুলি অনেক দ্রুত এবং আপনি আরও আইটেম যুক্ত করার সাথে ধীরে ধীরে হ্রাস করবেন না, সুতরাং দ্বিতীয় বিপরীত অভিধানটি বড় তালিকাগুলির মধ্যে মহাকাব্য পরিমাণটি সাশ্রয় করবে। এটি প্রাসঙ্গিক নাও হতে পারে তবে এটি সাজানোর জিনিস যা পরীক্ষার সময় অল্প পরিমাণে ডেটা দিয়ে সূক্ষ্ম হতে পারে এবং তারপরে এটি গুরুতর ডেটা সহ সত্যিকারের সার্ভারে অভিনয়কে খুন করে mur
স্টিভ কুপার

1

এটি একটি পুরানো সমস্যা তবে কেউ যদি এটির কাজে লাগে সে ক্ষেত্রে আমি দুটি এক্সটেনশন পদ্ধতি যুক্ত করতে চেয়েছিলাম। দ্বিতীয়টি তেমন দরকারী নয় তবে এটি যদি একটি থেকে এক অভিধানকে সমর্থন করার প্রয়োজন হয় তবে এটি একটি সূচনা পয়েন্ট সরবরাহ করে।

    public static Dictionary<VALUE,KEY> Inverse<KEY,VALUE>(this Dictionary<KEY,VALUE> dictionary)
    {
        if (dictionary==null || dictionary.Count == 0) { return null; }

        var result = new Dictionary<VALUE, KEY>(dictionary.Count);

        foreach(KeyValuePair<KEY,VALUE> entry in dictionary)
        {
            result.Add(entry.Value, entry.Key);
        }

        return result;
    }

    public static Dictionary<VALUE, KEY> SafeInverse<KEY, VALUE>(this Dictionary<KEY, VALUE> dictionary)
    {
        if (dictionary == null || dictionary.Count == 0) { return null; }

        var result = new Dictionary<VALUE, KEY>(dictionary.Count);

        foreach (KeyValuePair<KEY, VALUE> entry in dictionary)
        {
            if (result.ContainsKey(entry.Value)) { continue; }

            result.Add(entry.Value, entry.Key);
        }

        return result;
    }

1

জাভেয়ার জন এর উত্তরের একটি পরিবর্তিত সংস্করণ, অতিরিক্ত তুলনাকারীকে এগিয়ে নেওয়া এবং তুলনামূলক তুলনায় অতিরিক্ত নির্মাতা। উদাহরণস্বরূপ এটি কেস-সংবেদনশীল কীগুলিকে সমর্থন করবে। ফরোয়ার্ড এবং বিপরীত অভিধান নির্মাণকারীদের আরও যুক্তি পাস করার জন্য আরও কনস্ট্রাক্টর যুক্ত করা যেতে পারে।

public class Map<T1, T2> : IEnumerable<KeyValuePair<T1, T2>>
{
    private readonly Dictionary<T1, T2> _forward;
    private readonly Dictionary<T2, T1> _reverse;

    /// <summary>
    /// Constructor that uses the default comparers for the keys in each direction.
    /// </summary>
    public Map()
        : this(null, null)
    {
    }

    /// <summary>
    /// Constructor that defines the comparers to use when comparing keys in each direction.
    /// </summary>
    /// <param name="t1Comparer">Comparer for the keys of type T1.</param>
    /// <param name="t2Comparer">Comparer for the keys of type T2.</param>
    /// <remarks>Pass null to use the default comparer.</remarks>
    public Map(IEqualityComparer<T1> t1Comparer, IEqualityComparer<T2> t2Comparer)
    {
        _forward = new Dictionary<T1, T2>(t1Comparer);
        _reverse = new Dictionary<T2, T1>(t2Comparer);
        Forward = new Indexer<T1, T2>(_forward);
        Reverse = new Indexer<T2, T1>(_reverse);
    }

    // Remainder is the same as Xavier John's answer:
    // https://stackoverflow.com/a/41907561/216440
    ...
}

কেস-সংবেদনশীল কী সহ ব্যবহারের উদাহরণ:

Map<int, string> categories = 
new Map<int, string>(null, StringComparer.CurrentCultureIgnoreCase)
{
    { 1, "Bedroom Furniture" },
    { 2, "Dining Furniture" },
    { 3, "Outdoor Furniture" }, 
    { 4, "Kitchen Appliances" }
};

int categoryId = 3;
Console.WriteLine("Description for category ID {0}: '{1}'", 
    categoryId, categories.Forward[categoryId]);

string categoryDescription = "DINING FURNITURE";
Console.WriteLine("Category ID for description '{0}': {1}", 
    categoryDescription, categories.Reverse[categoryDescription]);

categoryDescription = "outdoor furniture";
Console.WriteLine("Category ID for description '{0}': {1}", 
    categoryDescription, categories.Reverse[categoryDescription]);

// Results:
/*
Description for category ID 3: 'Outdoor Furniture'
Category ID for description 'DINING FURNITURE': 2
Category ID for description 'outdoor furniture': 3
*/

1

আমার কোড এখানে। বীজযুক্ত কনস্ট্রাক্টর ব্যতীত সমস্ত কিছুই ও (1)।

using System.Collections.Generic;
using System.Linq;

public class TwoWayDictionary<T1, T2>
{
    Dictionary<T1, T2> _Forwards = new Dictionary<T1, T2>();
    Dictionary<T2, T1> _Backwards = new Dictionary<T2, T1>();

    public IReadOnlyDictionary<T1, T2> Forwards => _Forwards;
    public IReadOnlyDictionary<T2, T1> Backwards => _Backwards;

    public IEnumerable<T1> Set1 => Forwards.Keys;
    public IEnumerable<T2> Set2 => Backwards.Keys;


    public TwoWayDictionary()
    {
        _Forwards = new Dictionary<T1, T2>();
        _Backwards = new Dictionary<T2, T1>();
    }

    public TwoWayDictionary(int capacity)
    {
        _Forwards = new Dictionary<T1, T2>(capacity);
        _Backwards = new Dictionary<T2, T1>(capacity);
    }

    public TwoWayDictionary(Dictionary<T1, T2> initial)
    {
        _Forwards = initial;
        _Backwards = initial.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
    }

    public TwoWayDictionary(Dictionary<T2, T1> initial)
    {
        _Backwards = initial;
        _Forwards = initial.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
    }


    public T1 this[T2 index]
    {
        get => _Backwards[index];
        set
        {
            if (_Backwards.TryGetValue(index, out var removeThis))
                _Forwards.Remove(removeThis);

            _Backwards[index] = value;
            _Forwards[value] = index;
        }
    }

    public T2 this[T1 index]
    {
        get => _Forwards[index];
        set
        {
            if (_Forwards.TryGetValue(index, out var removeThis))
                _Backwards.Remove(removeThis);

            _Forwards[index] = value;
            _Backwards[value] = index;
        }
    }

    public int Count => _Forwards.Count;

    public bool Contains(T1 item) => _Forwards.ContainsKey(item);
    public bool Contains(T2 item) => _Backwards.ContainsKey(item);

    public bool Remove(T1 item)
    {
        if (!this.Contains(item))
            return false;

        var t2 = _Forwards[item];

        _Backwards.Remove(t2);
        _Forwards.Remove(item);

        return true;
    }

    public bool Remove(T2 item)
    {
        if (!this.Contains(item))
            return false;

        var t1 = _Backwards[item];

        _Forwards.Remove(t1);
        _Backwards.Remove(item);

        return true;
    }

    public void Clear()
    {
        _Forwards.Clear();
        _Backwards.Clear();
    }
}

আমি অবাক হয়েছি যে আপনি যদি কোনও বিদ্যমান অভিধান পাস করেন যেখানে কী এবং মানের ধরণগুলি একই থাকে তবে নির্মাতারা কীভাবে আচরণ করবে। পিছনের দিকে বনাম ফরোয়ার্ডগুলি ব্যবহার করা হবে কিনা তা কীভাবে সমাধান হবে?
কলম্ব ভান্ডাল

0

নিম্নলিখিত এনক্যাপসুলেটিং ক্লাসটি 1 অভিধান উদাহরণের তুলনায় লিনক (আইনিউমারেবল এক্সটেনশানস) ব্যবহার করে।

public class TwoWayDictionary<TKey, TValue>
{
    readonly IDictionary<TKey, TValue> dict;
    readonly Func<TKey, TValue> GetValueWhereKey;
    readonly Func<TValue, TKey> GetKeyWhereValue;
    readonly bool _mustValueBeUnique = true;

    public TwoWayDictionary()
    {
        this.dict = new Dictionary<TKey, TValue>();
        this.GetValueWhereKey = (strValue) => dict.Where(kvp => Object.Equals(kvp.Key, strValue)).Select(kvp => kvp.Value).FirstOrDefault();
        this.GetKeyWhereValue = (intValue) => dict.Where(kvp => Object.Equals(kvp.Value, intValue)).Select(kvp => kvp.Key).FirstOrDefault();
    }

    public TwoWayDictionary(KeyValuePair<TKey, TValue>[] kvps)
        : this()
    {
        this.AddRange(kvps);
    }

    public void AddRange(KeyValuePair<TKey, TValue>[] kvps)
    {
        kvps.ToList().ForEach( kvp => {        
            if (!_mustValueBeUnique || !this.dict.Any(item => Object.Equals(item.Value, kvp.Value)))
            {
                dict.Add(kvp.Key, kvp.Value);
            } else {
                throw new InvalidOperationException("Value must be unique");
            }
        });
    }

    public TValue this[TKey key]
    {
        get { return GetValueWhereKey(key); }
    }

    public TKey this[TValue value]
    {
        get { return GetKeyWhereValue(value); }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var dict = new TwoWayDictionary<string, int>(new KeyValuePair<string, int>[] {
            new KeyValuePair<string, int>(".jpeg",100),
            new KeyValuePair<string, int>(".jpg",101),
            new KeyValuePair<string, int>(".txt",102),
            new KeyValuePair<string, int>(".zip",103)
        });


        var r1 = dict[100];
        var r2 = dict[".jpg"];

    }

}

0

বিপরীত অনুসন্ধানের জন্য এটি একটি সূচক ব্যবহার করে।
বিপরীত অনুসন্ধান ও (এন) তবে এটি দুটি অভিধানও ব্যবহার করে না

public sealed class DictionaryDoubleKeyed : Dictionary<UInt32, string>
{   // used UInt32 as the key as it has a perfect hash
    // if most of the lookup is by word then swap
    public void Add(UInt32 ID, string Word)
    {
        if (this.ContainsValue(Word)) throw new ArgumentException();
        base.Add(ID, Word);
    }
    public UInt32 this[string Word]
    {   // this will be O(n)
        get
        {
            return this.FirstOrDefault(x => x.Value == Word).Key;
        }
    } 
}

উদাহরণস্বরূপ: সম্ভব এনআরই ইন this[string Word]। অতিরিক্ত সমস্যাগুলি পরিবর্তনশীল নামগুলি সাধারণ UInt16UInt32
রীতিগুলির সাথে সামঞ্জস্য

0

পরামর্শ দেওয়া হয়েছিল তাদের একটি বিকল্প সমাধান এখানে। আইটেমগুলি যুক্ত / অপসারণের সময় অভ্যন্তরীণ শ্রেণিটি সরিয়ে ফেলা হয়েছে এবং সমন্বয়টি বীমাকৃত করে

using System.Collections;
using System.Collections.Generic;

public class Map<E, F> : IEnumerable<KeyValuePair<E, F>>
{
    private readonly Dictionary<E, F> _left = new Dictionary<E, F>();
    public IReadOnlyDictionary<E, F> left => this._left;
    private readonly Dictionary<F, E> _right = new Dictionary<F, E>();
    public IReadOnlyDictionary<F, E> right => this._right;

    public void RemoveLeft(E e)
    {
        if (!this.left.ContainsKey(e)) return;
        this._right.Remove(this.left[e]);
        this._left.Remove(e);
    }

    public void RemoveRight(F f)
    {
        if (!this.right.ContainsKey(f)) return;
        this._left.Remove(this.right[f]);
        this._right.Remove(f);
    }

    public int Count()
    {
        return this.left.Count;
    }

    public void Set(E left, F right)
    {
        if (this.left.ContainsKey(left))
        {
            this.RemoveLeft(left);
        }
        if (this.right.ContainsKey(right))
        {
            this.RemoveRight(right);
        }
        this._left.Add(left, right);
        this._right.Add(right, left);
    }


    public IEnumerator<KeyValuePair<E, F>> GetEnumerator()
    {
        return this.left.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.left.GetEnumerator();
    }
}


0

BijectionDictionaryএই ওপেন সোর্স রেপোতে একটি প্রকার পাওয়া যায়:

https://github.com/ColmBhandal/CsharpExtras

এটি দেওয়া অন্যান্য উত্তরগুলির তুলনায় গুণগতভাবে অনেক বেশি আলাদা নয়। এটি বেশিরভাগ উত্তরগুলির মতো দুটি অভিধান ব্যবহার করে।

উপন্যাসটি কী, আমি বিশ্বাস করি, এই অভিধানটি বনাম অন্যান্য উত্তর সম্পর্কে এখন পর্যন্ত, এটি দ্বিমুখী অভিধানের মতো আচরণ করার পরিবর্তে এটি কেবল একমুখী, পরিচিত অভিধানের মতো আচরণ করে এবং তারপরে গতিশীলভাবে আপনাকে অভিধানটি সরিয়ে ফেলার অনুমতি দেয় বিপরীত সম্পত্তি। উল্টানো বস্তুর রেফারেন্স অগভীর, সুতরাং এটি এখনও মূল রেফারেন্সের মতো একই মূল বিষয়টিকে পরিবর্তন করতে সক্ষম হবে। সুতরাং আপনি একই অবজেক্টের দুটি রেফারেন্স পেতে পারেন, তার মধ্যে একটিও ফ্লিপ না করে।

এই অভিধানটি সম্পর্কে সম্ভবত অনন্য একটি জিনিস যা এই রেপোর অধীনে পরীক্ষার প্রকল্পে এর জন্য কিছু পরীক্ষা লেখা রয়েছে। এটি অনুশীলনে আমাদের ব্যবহার করা হয়েছে এবং এখনও অবধি স্থিতিশীল রয়েছে।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.