কীভাবে আমি নেট থেকে কোনও আইনিউমেবল <T> থেকে প্রথম উপাদানটি পেতে পারি?


156

আমি প্রায়শই IEnumerable<T>ইন-নেট এর প্রথম উপাদানটি ধরতে চাই এবং এটি করার কোনও ভাল উপায় আমি খুঁজে পাইনি। আমি যে সেরাটি নিয়ে এসেছি তা হ'ল:

foreach(Elem e in enumerable) {
  // do something with e
  break;
}

ইশ! সুতরাং, এটি করার একটি দুর্দান্ত উপায় আছে?

উত্তর:


241

আপনি যদি লিনকিউ ব্যবহার করতে পারেন তবে আপনি ব্যবহার করতে পারেন:

var e = enumerable.First();

এটি একটি ব্যতিক্রম ছুঁড়ে ফেলবে যদিও অগণনীয় খালি থাকলে: এক্ষেত্রে আপনি ব্যবহার করতে পারেন:

var e = enumerable.FirstOrDefault();

FirstOrDefault()default(T)যদি গণনাটি খালি থাকে তবে তা ফিরে আসবে , যা nullউল্লেখের ধরণের জন্য বা মান ধরণের জন্য ডিফল্ট 'শূন্য-মান' হবে।

আপনি যদি লিনকিউ ব্যবহার করতে না পারেন, তবে আপনার পদ্ধতিটি প্রযুক্তিগতভাবে সঠিক এবং প্রথম ফলাফলটি পুনরুদ্ধার করার জন্য পদ্ধতিগুলি GetEnumeratorএবং MoveNextপদ্ধতি ব্যবহার করে একটি গণক তৈরির চেয়ে আলাদা নয় (এই উদাহরণটি গণনাযোগ্য হ'ল একটি IEnumerable<Elem>):

Elem e = myDefault;
using (IEnumerator<Elem> enumer = enumerable.GetEnumerator()) {
    if (enumer.MoveNext()) e = enumer.Current;
}

জোয়েল কোহোর্ন.Single() মন্তব্যগুলিতে উল্লেখ করেছেন; এটিও কার্যকর হবে, যদি আপনি নিজের সংখ্যাটি হুবহু একটি উপাদান অন্তর্ভুক্ত করে রাখার প্রত্যাশা করে থাকেন - তবে এটি যদি একটি উপাদান থেকে খালি বা বড় হয় তবে এটি ব্যতিক্রম করবে will একটি অনুরূপ SingleOrDefault()পদ্ধতি রয়েছে যা একই দৃশ্যে এই দৃশ্যটি coversেকে দেয় FirstOrDefault()। যাইহোক, ডেভিড বি ব্যাখ্যা করেছেন যে SingleOrDefault()গণনার ক্ষেত্রে একাধিক আইটেম রয়েছে এমন ক্ষেত্রে এখনও একটি ব্যতিক্রম হতে পারে।

সম্পাদনা করুন: মার্ক মার্ক গ্র্যাভেলকে উল্লেখ করার জন্য ধন্যবাদ যে আমার জিনিসটি ব্যবহার করার IEnumeratorপরে তা নিষ্পত্তি করতে হবে - আমি usingএই প্যাটার্নটি বাস্তবায়নের জন্য কীওয়ার্ডটি প্রদর্শনের জন্য নন-লিনক উদাহরণ সম্পাদনা করেছি ।


2
সিঙ্গেলঅরডিফল্ট ফিরে আসবে বলে উল্লেখযোগ্য 1) কেবলমাত্র একটি আইটেম থাকলে একমাত্র আইটেম। 2) কোনও আইটেম না থাকলে নাল। ৩) একাধিক আইটেম থাকলে ব্যতিক্রম ছুঁড়ে দিন।
অ্যামি বি

ভাল কল ডেভিড বি - একটি নোট যুক্ত।
এরিক ফোর্বস

36

আপনি যদি নেট নেট ২.০ ব্যবহার করছেন এবং লিনকিউতে অ্যাক্সেস না পেয়ে থাকেন তবে:

 static T First<T>(IEnumerable<T> items)
 {
     using(IEnumerator<T> iter = items.GetEnumerator())
     {
         iter.MoveNext();
         return iter.Current;
     }
 }

এটি আপনি যা খুঁজছেন তা করা উচিত ... এটি জেনেরিকগুলি ব্যবহার করে যাতে আপনি যেকোন প্রকারের আইমনামেবলের প্রথম আইটেমটি পেতে পারেন।

এটি যেমন কল:

List<string> items = new List<string>() { "A", "B", "C", "D", "E" };
string firstItem = First<string>(items);

অথবা

int[] items = new int[] { 1, 2, 3, 4, 5 };
int firstItem = First<int>(items);

.NET 3.5 এর IEnumerable.ElementAt () এক্সটেনশন পদ্ধতির নকল করার জন্য আপনি এটি সহজেই পর্যাপ্ত পরিমাণে পরিবর্তন করতে পারেন:

static T ElementAt<T>(IEnumerable<T> items, int index)
{
    using(IEnumerator<T> iter = items.GetEnumerator())
    {
        for (int i = 0; i <= index; i++, iter.MoveNext()) ;
        return iter.Current;
    }
} 

এটিকে এভাবে কল করা:

int[] items = { 1, 2, 3, 4, 5 };
int elemIdx = 3;
int item = ElementAt<int>(items, elemIdx);

অবশ্যই আপনি কি LINQ অ্যাক্সেস না থেকে থাকে তাহলে ভাল উত্তর প্রচুর ইতিমধ্যে পোস্ট হয় ...


উফ, অবশ্যই আপনি ঠিক বলেছেন, ধন্যবাদ। আমি আমার উদাহরণ সংশোধন করেছি।
বেনআলাবাস্টার

আপনি যদি ২.০ এ থাকেন তবে আপনারও বৈচিত্র নেই।
30:32

1
আমি অনুমান করি আপনি যদি
চূড়ান্ত হতে

কেউ নেট .০.০.০ ব্যবহার করে আটকে গিয়েছেন, এটির প্রশংসা হয়েছিল! যশ।
kayleeFrye_onDeck

26

ঠিক আছে, আপনি .NET এর কোন সংস্করণটি নির্দিষ্ট করেন নি।

ধরে নিলাম আপনার 3.5 আছে, অন্য একটি উপায় এলিমেন্টআট পদ্ধতি:

var e = enumerable.ElementAt(0);

2
এলিমেন্টআউট (0), দুর্দান্ত এবং সাধারণ।
জেএমডি


1

এটা চেষ্টা কর

IEnumberable<string> aa;
string a = (from t in aa where t.Equals("") select t.Value).ToArray()[0];

0

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


1
এখানে কী প্রমাণ রয়েছে যে গণককে এড়ানো উচিত? আমার মেশিনে পারফরম্যান্স পরীক্ষাগুলি ইঙ্গিত দেয় যে এটি ফোরচের তুলনায় প্রায় 10% পারফরম্যান্স লাভ করেছে।
BenAlabaster

এটি নির্ভর করে আপনি কী গণনা করছেন on আমার ধারণা, কোনও ইমুরেটর ডাটাবেসের সাথে সংযোগ বন্ধ করতে পারে, ফাইল হ্যান্ডল বন্ধ করতে পারে, কিছু লক করা অবজেক্ট প্রকাশ করতে পারে। কিছু সংখ্যার তালিকার একজন এনমিটারকে নিষ্পত্তি না করা ক্ষতিগ্রস্থ হবে না, আমার ধারণা।
মৌক 13

0

যদি আপনার IEnumerable এটি প্রকাশ করে না <T>এবং লিনক ব্যর্থ হয়, আপনি প্রতিবিম্ব ব্যবহার করে একটি পদ্ধতি লিখতে পারেন:

public static T GetEnumeratedItem<T>(Object items, int index) where T : class
{
  T item = null;
  if (items != null)
  {
    System.Reflection.MethodInfo mi = items.GetType()
      .GetMethod("GetEnumerator");
    if (mi != null)
    {
      object o = mi.Invoke(items, null);
      if (o != null)
      {
        System.Reflection.MethodInfo mn = o.GetType()
          .GetMethod("MoveNext");
        if (mn != null)
        {
          object next = mn.Invoke(o, null);
          while (next != null && next.ToString() == "True")
          {
            if (index < 1)
            {
              System.Reflection.PropertyInfo pi = o
                .GetType().GetProperty("Current");
              if (pi != null) item = pi
                .GetValue(o, null) as T;
              break;
            }
            index--;
          }
        }
      }
    }
  }
  return item;
}

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