একটি সংখ্যাসূচক সূচকের মাধ্যমে অভিধানে অ্যাক্সেস করা হচ্ছে। কী কী


160

আমি এমন একটি ব্যবহার করছি Dictionary<string, int>যেখানে intকীটির একটি গণনা।

এখন, অভিধানের ভিতরে আমার সর্বশেষ sertedোকানো কীটি অ্যাক্সেস করা দরকার, তবে আমি এর নাম জানি না। সুস্পষ্ট প্রচেষ্টা:

int LastCount = mydict[mydict.keys[mydict.keys.Count]];

কাজ করে না, কারণ Dictionary.Keysকোনও [] -indexer প্রয়োগ করে না।

আমি শুধু ভাবছি কি এরকম কোন ক্লাস আছে কিনা? আমি স্ট্যাক ব্যবহার সম্পর্কে ভেবেছিলাম, তবে এটি কেবল স্ট্রিং সঞ্চয় করে। আমি এখন আমার নিজস্ব কাঠামো তৈরি করতে পারি এবং তার পরে একটি ব্যবহার করতে পারি Stack<MyStruct>, তবে আমি ভাবছি কী অন্য কোনও বিকল্প আছে, মূলত একটি অভিধান রয়েছে যা কীগুলিতে একটি [] -indexer প্রয়োগ করে?


1
আপনি যদি সেই ভেরিয়েবলটি বক্স করেন তবে কী হবে?
পল প্রেওয়েট

উত্তর:


222

@ ফ্যালানভে যেমন একটি মন্তব্যে উল্লেখ করেছেন, এরকম কিছু করা ভুল :

int LastCount = mydict.Keys.ElementAt(mydict.Count -1);

আপনার অভিধানের কীগুলির ক্রমের উপর নির্ভর করা উচিত নয় । আপনি ক্রম প্রয়োজন হয়, তাহলে আপনি একটি ব্যবহার করা উচিত OrderedDictionary হিসাবে এই প্রস্তাব, উত্তর । এই পৃষ্ঠায় অন্যান্য উত্তর এছাড়াও আকর্ষণীয়।


1
HashTableসিস্টেম.কলেশনস-আইক্লিকেশন'এর সাথে কাজ করছে না বলে মনে হচ্ছে 'এলিমেন্টআট' এর সংজ্ঞা নেই এবং কোনও 'এক্সটেনশান.কলেকশন' টাইপের প্রথম আর্গুমেন্ট গ্রহণ করে কোনও এলিমেন্টআট 'এলিমেন্টআট' পাওয়া যায়নি
v.oddou

আপনি ElementAtOrDefaultব্যতিক্রমী সংস্করণ দিয়ে কাজ করতে সংস্করণ ব্যবহার করতে পারেন ।
তারেক অ্যাজগান গোনার

22
এই ধরণের স্পষ্টত ভুল উত্তর গৃহীত হওয়া এবং এটি অনেকটা আপত্তিকর হওয়া দেখতে ভীতিকর। এটি ভুল কারণ Dictionary<TKey,TValue>ডকুমেন্টেশন হিসাবে "" কীগুলির Dictionary<TKey, TValue>.KeyCollectionক্রমটি অনির্ধারিত। " অর্ডারটি mydict.Count -1
অপরিশোধিত

এটি ভীতিজনক ... তবে যেহেতু আমি আমার সন্দেহের নিশ্চয়তার সন্ধান করছিলাম তখন থেকে আপনি সহায়ক যে আপনি আদেশের উপর নির্ভর করতে পারবেন না !!! ধন্যবাদ @ ফ্যালানওয়ে
চার্লি

3
কিছু ক্ষেত্রে অর্ডার প্রাসঙ্গিক নয় - কেবল আপনি সমস্ত কীটি পেরিয়ে গেছেন তা এই সত্য।
রয়াই মিন্ডেল

59

আপনি একটি অর্ডারড অভিধান ব্যবহার করতে পারেন ।

কী বা মান জোড়ের সংকলন যা কী বা সূচক দ্বারা অ্যাক্সেসযোগ্য তা উপস্থাপন করে।


42
এরহম, 19 টি উত্থানের পরেও, কেউই উল্লেখ করেনি যে অর্ডারডডিয়েশনারি এখনও সূচক অনুসারে কীটি পেতে দেয় না?
ল্যাজলো

1
আপনি অর্ডারডোরিজ দিয়ে পূর্ণসংখ্য সূচক সহ কোনও মান অ্যাক্সেস করতে পারেন তবে সিস্টেমের সাথে নয় not সংগ্রহ lections জেনেরিক.সোর্টড অভিধান <টি কে, টিভিালু> যেখানে সূচকটি টিকে হওয়া দরকার
ম্যাক্সেন্স

অর্ডারডিয়েশনারি নাম যুক্ত করা হয়েছিল একই ক্রমে উপাদানগুলি বজায় রাখতে এই সংগ্রহের ক্রিয়াকলাপের সাথে সম্পর্কিত। কিছু ক্ষেত্রে, একটি অর্ডারের সাজানোর মতো একই অর্থ রয়েছে তবে এই সংগ্রহে নেই।
শারুনাস বিয়েলস্কিস

18

একটি অভিধান হ্যাশ টেবিল, সুতরাং আপনার সন্নিবেশয়ের ক্রমটি ধারণা নেই!

আপনি যদি সর্বপ্রথম sertedোকানো কীটি জানতে চান তবে আমি একটি শেষকিনাইন্ডার্ড মান অন্তর্ভুক্ত করার জন্য অভিধানটি প্রসারিত করার পরামর্শ দেব।

উদাহরণ:

public MyDictionary<K, T> : IDictionary<K, T>
{
    private IDictionary<K, T> _InnerDictionary;

    public K LastInsertedKey { get; set; }

    public MyDictionary()
    {
        _InnerDictionary = new Dictionary<K, T>();
    }

    #region Implementation of IDictionary

    public void Add(KeyValuePair<K, T> item)
    {
        _InnerDictionary.Add(item);
        LastInsertedKey = item.Key;

    }

    public void Add(K key, T value)
    {
        _InnerDictionary.Add(key, value);
        LastInsertedKey = key;
    }

    .... rest of IDictionary methods

    #endregion

}

আপনি সমস্যাগুলিতে দৌড়াবেন তবে আপনি যখন এটি ব্যবহার করেন .Remove()তখন এটি কাটিয়ে উঠতে আপনাকে কীগুলির একটি আদেশযুক্ত তালিকা inোকাতে হবে।


8

একটি শেষ কী sertedোকানো সম্পত্তি যুক্ত করতে আপনি কেবল অভিধান ক্লাসটি প্রসারিত করবেন না কেন। নিম্নলিখিত মত কিছু হতে পারে?

public class ExtendedDictionary : Dictionary<string, int>
{
    private int lastKeyInserted = -1;

    public int LastKeyInserted
    {
        get { return lastKeyInserted; }
        set { lastKeyInserted = value; }
    }

    public void AddNew(string s, int i)
    {
        lastKeyInserted = i;

        base.Add(s, i);
    }
}

2
Lastোকানো সর্বশেষ মানটিতে আপনি সর্বশেষ কী সেট করেছেন। হয় আপনি এটিকে সর্বশেষ কীটি sertedোকানোতে সেট করতে চেয়েছিলেন বা ভেরিয়েবল এবং সম্পত্তির জন্য আপনার আরও ভাল নাম প্রয়োজন।
ফ্যানটিয়াস

6

আপনি সর্বদা এটি করতে পারেন:

string[] temp = new string[mydict.count];
mydict.Keys.CopyTo(temp, 0)
int LastCount = mydict[temp[mydict.count - 1]]

তবে আমি এটি সুপারিশ করব না। সর্বশেষ sertedোকানো কী অ্যারের শেষে থাকবে এমন কোনও গ্যারান্টি নেই। এমএসডিএন-তে কীগুলির অর্ডারিংটি অনির্ধারিত এবং পরিবর্তিত হতে পারে। আমার খুব সংক্ষিপ্ত পরীক্ষায় এটি সন্নিবেশের ক্রম হিসাবে মনে হচ্ছে তবে আপনি স্ট্যাকের মতো যথাযথ হিসাবরক্ষক তৈরির চেয়ে ভাল হবেন - যেমন আপনি পরামর্শ দিয়েছেন (যদিও আমি আপনার ভিত্তিতে কাঠামোর প্রয়োজন দেখছি না) অন্যান্য বিবৃতি) - অথবা একক ভেরিয়েবল ক্যাশে যদি আপনাকে কেবল সর্বশেষ কীটি জানতে হবে to


5

আমি মনে করি আপনি এরকম কিছু করতে পারেন, বাক্য গঠনটি ভুল হতে পারে, শেষ আইটেমটি পেতে কিছুক্ষণ C # ব্যবহার করেন নি

Dictionary<string, int>.KeyCollection keys = mydict.keys;
string lastKey = keys.Last();

অথবা সর্বাধিক মান পেতে শেষের পরিবর্তে সর্বোচ্চ ব্যবহার করুন, আমি জানি না কোনটি আপনার কোডের সাথে আরও ভাল ফিট করে।


2
আমি যুক্ত করব যেহেতু "সর্বশেষ ()" একটি এক্সটেনশন পদ্ধতি তাই আপনার .cs ফাইলের শীর্ষে "নেট। ফ্রেমওয়ার্ক 3.5 ব্যবহার করতে হবে এবং" সিস্টেম.লিনিক ব্যবহার করে "যুক্ত করতে হবে।
সুপারওলি

শেষের জন্য এটি চেষ্টা করুন (যখন কোনও ডিস্ট্রিং <স্ট্রিং, স্ট্রিং> স্পষ্টত :-) কীভ্যালিউপায়ার <স্ট্রিং, স্ট্রিং> শেষ = oAuthPair.Last () ব্যবহার করুন; if (kvp.Key! = last.Key) {_oauth_ParamString = _oauth_ParamString + "&"; }
টিম উইন্ডসর

4

আমি প্যাট্রিকের উত্তরের দ্বিতীয় অংশের সাথে একমত এমনকি যদি কিছু পরীক্ষায় এটি সন্নিবেশের আদেশ রাখে বলে মনে হয়, তবে ডকুমেন্টেশন (এবং অভিধান এবং হ্যাশগুলির জন্য স্বাভাবিক আচরণ) স্পষ্টভাবে জানিয়ে দেয় যে আদেশটি অনির্দিষ্ট।

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


4

আপনি যদি ভাঙা সাপেক্ষে বিপজ্জনক কোডটি ব্যবহার করার সিদ্ধান্ত নেন তবে এই এক্সটেনশন ফাংশনটি Dictionary<K,V>তার অভ্যন্তরীণ সূচী অনুসারে একটি থেকে একটি কী এনে দেবে (যা মনো এবং এন। নেট এর জন্য বর্তমানে একই ক্রমে উপস্থিত বলে মনে হচ্ছে আপনি অঙ্কটি দিয়ে যাচ্ছেনKeys সম্পত্তি )।

লিনক ব্যবহার করা অনেক বেশি পছন্দনীয়: dict.Keys.ElementAt(i)তবে এই ফাংশনটি ও (এন) এর পুনরাবৃত্তি করবে; নিম্নলিখিতটি হে (1) তবে একটি প্রতিবিম্ব পারফরম্যান্স পেনাল্টি সহ।

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

public static class Extensions
{
    public static TKey KeyByIndex<TKey,TValue>(this Dictionary<TKey, TValue> dict, int idx)
    {
        Type type = typeof(Dictionary<TKey, TValue>);
        FieldInfo info = type.GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance);
        if (info != null)
        {
            // .NET
            Object element = ((Array)info.GetValue(dict)).GetValue(idx);
            return (TKey)element.GetType().GetField("key", BindingFlags.Public | BindingFlags.Instance).GetValue(element);
        }
        // Mono:
        info = type.GetField("keySlots", BindingFlags.NonPublic | BindingFlags.Instance);
        return (TKey)((Array)info.GetValue(dict)).GetValue(idx);
    }
};

হুঁ, উত্তরটি উন্নত করতে সম্পাদনা একটি ডাউনভোট অর্জন করেছে। কোডটি (স্পষ্টতই) ঘৃণ্য এবং আমি সে অনুযায়ী পরিষ্কারভাবে বিবেচনা করা উচিত না?
গ্লেন স্লেডেন

4

যদি কীটি মানটিতে এম্বেড করা থাকে তবে একটি বিকল্প হ'ল কেয়েডক্লাকশন

সিল করা ক্লাসটি ব্যবহারের জন্য কেবল একটি প্রাথমিক প্রয়োগ তৈরি করুন।

সুতরাং প্রতিস্থাপন Dictionary<string, int>(যা একটি খুব ভাল উদাহরণ না হিসাবে কোন int জন্য একটি পরিষ্কার কী নেই)।

private sealed class IntDictionary : KeyedCollection<string, int>
{
    protected override string GetKeyForItem(int item)
    {
        // The example works better when the value contains the key. It falls down a bit for a dictionary of ints.
        return item.ToString();
    }
}

KeyedCollection<string, int> intCollection = new ClassThatContainsSealedImplementation.IntDictionary();

intCollection.Add(7);

int valueByIndex = intCollection[0];

কী সম্পর্কে আপনার মন্তব্য সম্পর্কে, আমার এইটির উত্তর অনুসরণ করুন।
টকরল

3

আপনি যেভাবে প্রশ্নটি উত্তর দিয়েছেন তা আমাকে বিশ্বাস করতে পরিচালিত করে যে অভিধানে অন্তর্নিহিতভাবে অভিধানে আইটেমটির "অবস্থান" থাকে। কীগুলি যুক্ত করা হয় না সেভাবে সেগুলি সংরক্ষণ করা হয়নি, এই দৃ from়তার সাথে বিচার করে যদি এটি সঠিক হয় তবে এর অর্থ হবে কীগুলি C অ্যাকাউন্ট (বা। হিসাব - 1, আপনি শূন্য-ভিত্তিক ব্যবহার করছেন) এখনও থাকা উচিত সর্বদা শেষ-প্রবেশের কীটির সংখ্যা হবে?

যদি এটি সঠিক হয় তবে এর পরিবর্তে অভিধান <ব্যবহার, অক্ষর> ব্যবহার করতে পারবেন না এমন কোনও কারণ রয়েছে যাতে আপনি মাইডিক্ট [mydict.Keys.Count] ব্যবহার করতে পারেন?


2

আমি জানি না এটি কীভাবে কাজ করবে কারণ আমি নিশ্চিত যে কীগুলি সেগুলি যুক্ত ক্রমে সংরক্ষণ করা হয়নি তবে আপনি কী তালিকাটি তালিকায় কাস্ট করতে পারেন এবং তারপরে তালিকার শেষ কীটি পেয়ে যাবেন ... তবে এটি একবার দেখার মতো হবে।

কেবলমাত্র অন্য একটি জিনিস যা আমি ভাবতে পারি তা হল অনুসন্ধান তালিকার কীগুলি সংরক্ষণ করা এবং আপনি অভিধানে যুক্ত করার আগে তালিকায় কীগুলি যুক্ত করা ... এটি খুব সুন্দর নয় ...


@ জুয়ান: মূল সংগ্রহটিতে নেই। (গত) পদ্ধতি নেই
লমাএক্সএক্স

আমি কোডটি পরীক্ষা করে দেখিনি, তবে পদ্ধতিটি [এমএসডিএন] [1] এ নথিভুক্ত হতে পারে [১] সম্ভবত এটির অন্য সংস্করণ কাঠামোটি? [১]: এমএসডিএন.মাইক্রোসফটকম /en-us/library/bb908406.aspx
জুয়ান

২ বছর দেরি হলেও এটি কাউকে সাহায্য করতে পারে ... নীচে জুয়ান পোস্টে আমার উত্তর দেখুন। শেষ () একটি এক্সটেনশন পদ্ধতি।
সুপারওলি

2

ড্যানিয়েল পোস্ট এবং কী সম্পর্কিত তার মন্তব্যগুলিতে প্রসারিত করতে, যেহেতু কীটি যে কোনওভাবে মানের মধ্যে এমবেড করা আছে, আপনি এটি ব্যবহার করতে পারেন KeyValuePair<TKey, TValue> মান হিসাবে এটি । এর মূল যুক্তিটি হ'ল, সাধারণভাবে, কীটি মূলত মান থেকে সরাসরি প্রাপ্ত হয় না।

তারপরে এটিকে দেখতে দেখতে লাগবে:

public sealed class CustomDictionary<TKey, TValue>
  : KeyedCollection<TKey, KeyValuePair<TKey, TValue>>
{
  protected override TKey GetKeyForItem(KeyValuePair<TKey, TValue> item)
  {
    return item.Key;
  }
}

পূর্ববর্তী উদাহরণ হিসাবে এটি ব্যবহার করতে, আপনি করতে:

CustomDictionary<string, int> custDict = new CustomDictionary<string, int>();

custDict.Add(new KeyValuePair<string, int>("key", 7));

int valueByIndex = custDict[0].Value;
int valueByKey = custDict["key"].Value;
string keyByIndex = custDict[0].Key;

2

রেফারেন্সের জন্য সূচকটি ব্যবহার করার জন্য একটি অভিধান খুব স্বজ্ঞাত নাও হতে পারে তবে কীভ্যালিউপায়ারের অ্যারের সাথে আপনার অনুরূপ ক্রিয়াকলাপ থাকতে পারে :

প্রাক্তন। KeyValuePair<string, string>[] filters;


2

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


1

ভিসুয়াল স্টুডিও এর UserVoice একটি লিঙ্ক দেয় জেনেরিক OrderedDictionary বাস্তবায়ন dotmore দ্বারা।

তবে যদি আপনাকে কেবল সূচি অনুসারে কী / মান জোড়া পেতে হয় এবং কীগুলির দ্বারা মান পেতে না হয় তবে আপনি একটি সহজ কৌশল ব্যবহার করতে পারেন। কিছু জেনেরিক শ্রেণি ঘোষণা করুন (আমি এটিকে তালিকাআরে বলেছি):

class ListArray<T> : List<T[]> { }

আপনি এটি নির্মাতাদের সাথেও ঘোষণা করতে পারেন:

class ListArray<T> : List<T[]>
{
    public ListArray() : base() { }
    public ListArray(int capacity) : base(capacity) { }
}

উদাহরণস্বরূপ, আপনি কোনও ফাইল থেকে কিছু কী / মান জুটি পড়েন এবং এগুলি সূচী দ্বারা পরে পাওয়ার জন্য সেগুলি পড়ার ক্রমে সংরক্ষণ করতে চান:

ListArray<string> settingsRead = new ListArray<string>();
using (var sr = new StreamReader(myFile))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {
        string[] keyValueStrings = line.Split(separator);
        for (int i = 0; i < keyValueStrings.Length; i++)
            keyValueStrings[i] = keyValueStrings[i].Trim();
        settingsRead.Add(keyValueStrings);
    }
}
// Later you get your key/value strings simply by index
string[] myKeyValueStrings = settingsRead[index];

আপনারা যেমন খেয়াল করেছেন, আপনার তালিকাআরেতে আপনার প্রয়োজন নেই কেবল কী / মানের জোড়। আইটেম অ্যারে যে কোনও দৈর্ঘ্যের হতে পারে, জেগড অ্যারেগুলির মতো।

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