লিনকু দিয়ে কোনও তালিকা ফাঁকা আছে কিনা তা পরীক্ষা করা হচ্ছে


122

কোনও তালিকা খালি কিনা তা নির্ধারণ করার জন্য "সেরা" (গতি এবং পাঠযোগ্যতা উভয় বিবেচনায় নেওয়া) কী? এমনকি তালিকাটি প্রকারভেদে IEnumerable<T>এবং একটি গণনা সম্পত্তি না থাকলেও।

এই মুহুর্তে আমি এর মধ্যে টস আপ করছি:

if (myList.Count() == 0) { ... }

এবং এই:

if (!myList.Any()) { ... }

আমার অনুমান যে দ্বিতীয় বিকল্পটি দ্রুততর, যেহেতু এটি প্রথম আইটেমটি দেখার সাথে সাথে ফলাফলের সাথে ফিরে আসবে, অন্যদিকে দ্বিতীয় বিকল্পটি (একটি গণনাকারীর জন্য) গণনা ফিরিয়ে আনার জন্য প্রতিটি আইটেম দেখতে হবে।

বলা হচ্ছে, দ্বিতীয় বিকল্পটি কি আপনার কাছে পঠনযোগ্য বলে মনে হচ্ছে? তুমি কোনটি পছন্দ করবে? অথবা আপনি খালি তালিকার জন্য আরও ভাল উপায় পরীক্ষা করতে পারেন?

সম্পাদনা @ লাসেভেকের প্রতিক্রিয়াটি সবচেয়ে যুক্তিসঙ্গত বলে মনে হচ্ছে, যদি সম্ভব হয় তবে ক্যাশেড গণনাটি ব্যবহার করতে কিছুটা রানটাইম চেকিংয়ের সাথে মিলিত হবে:

public static bool IsEmpty<T>(this IEnumerable<T> list)
{
    if (list is ICollection<T>) return ((ICollection<T>)list).Count == 0;

    return !list.Any();
}

5
ঢের বেশি ভাল মিশ্রিত করা না isএবং castকিন্তু ব্যবহার asএবং null: চেকICollection<T> collection = list as ICollection<T>; if (collection != null) return colllection.Count;
abatishchev

2
অতিরিক্ত পদ্ধতি কেন লিখবেন? list.Any()সমান নয় কি list.IsEmpty? কাঠামোর পদ্ধতিটি অনুকূলিত করা উচিত - এটি একটি নতুন বাধা কেবলমাত্র যদি আপনি বুঝতে পারেন যে এটি একটি পারফেক্ট বাধা।
dbkk

6
কেউ কি তাদের প্রস্তাবিত বাস্তবায়নগুলিতে পারফরম্যান্স পরিমাপ করতে বিরক্ত করেছিলেন বা প্রত্যেকেই কেবল ধারণা ফেলে দিচ্ছেন?
মাইকেল ব্রাউন

আমি .NET কোর শ্রেণীর লাইব্রেরিতে ইস্যু করার IsEmptyপদ্ধতিটি যুক্ত করার পরামর্শ দিয়েছি । github.com/dotnet/corefx/issues/35054 আপনি যদি চান এবং সম্মত হন তবে দয়া করে এটি পরীক্ষা করে ভোট দিন।
রাইতামুরোহশি

উত্তর:


100

আপনি এটি করতে পারেন:

public static Boolean IsEmpty<T>(this IEnumerable<T> source)
{
    if (source == null)
        return true; // or throw an exception
    return !source.Any();
}

সম্পাদনা করুন : নোট করুন যে অন্তর্নিহিত উত্সটিতে একটি দ্রুত গণনা সম্পত্তি আছে কেবলমাত্র। অ্যাকাউন্ট পদ্ধতি ব্যবহার করা দ্রুত হবে। উপরে একটি বৈধ অপ্টিমাইজেশন হ'ল কয়েকটি বেস প্রকারগুলি সনাক্ত করা এবং কেবলমাত্র .Any () পদ্ধতির পরিবর্তে those


4
অথবা একটি লাইন ব্যবহার করুন এবং কি ফেরত দিন (উত্স == নাল)? সত্য:! উত্স.আনি (); (আপনার একটি ব্যতিক্রম নিক্ষেপ না হলে)
Gage

1
আমি বলব, হ্যাঁ, শূন্যতার জন্য একটি ব্যতিক্রম ছুঁড়ে ফেলুন তবে তারপরে দ্বিতীয় একটি এক্সটেনশন পদ্ধতি যুক্ত করুন IsNullOrEmpty()
ডেভুসার

1
পাবলিক স্ট্যাটিক বুলিয়ান ইসনুলআরএম্পটি <টি> (এই অনুমানযোগ্য <টি> উত্স) {রিটার্ন উত্স == নাল || ! source.Any (); }
ডান

1
আজকাল @Gage:return !source?.Any() ?? true;

@ কৌশলগুলি আপডেটের জন্য ধন্যবাদ! আমি অবশ্যই এটি ব্যবহার করব!
গেজ

14

আপনি যে কোডটি স্থির করেছেন বলে মনে হচ্ছে তার সাথে আমি একটি ছোট সংযোজন করব: এটিও পরীক্ষা করে দেখুন ICollection, এটি কিছু অ-অপ্রচলিত জেনেরিক ক্লাস (যেমন, Queue<T>এবং Stack<T>) দ্বারা প্রয়োগ করা হয়েছে । আমি এটির asপরিবর্তে এটি ব্যবহার করব isকারণ এটি আরও মূর্তিযুক্ত এবং দ্রুত দেখানো হয়েছে

public static bool IsEmpty<T>(this IEnumerable<T> list)
{
    if (list == null)
    {
        throw new ArgumentNullException("list");
    }

    var genericCollection = list as ICollection<T>;
    if (genericCollection != null)
    {
        return genericCollection.Count == 0;
    }

    var nonGenericCollection = list as ICollection;
    if (nonGenericCollection != null)
    {
        return nonGenericCollection.Count == 0;
    }

    return !list.Any();
}

1
আমি এই উত্তর পছন্দ। সতর্কতার একটি শব্দ হ'ল কিছু সংগ্রহ ব্যতিক্রম ছুঁড়ে ফেলবে যখন তারা সম্পূর্ণরূপে NotSupportedExceptionবা এর মতো কোনও ইন্টারফেস প্রয়োগ করে না NotImplementedException। আমি প্রথমে আপনার কোড উদাহরণটি ব্যবহার করেছি যখন আমি একটি সংগ্রহটি ব্যবহার করছিলাম যা কাউন্টের (যিনি জানেন ...) এর জন্য ব্যতিক্রম ছুঁড়েছিলেন।
স্যাম

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

8

লিংক নিজেই অবশ্যই কোনওভাবে গণনা () পদ্ধতির চারপাশে কিছু গুরুতর অপ্টিমাইজেশন করছে।

এটা কি আপনাকে অবাক করে? আমি কল্পনা করি যে IListবাস্তবায়নের জন্য , Countসরাসরি উপাদানগুলির সংখ্যাটি সরাসরি পড়ে যখন পদ্ধতিটি Anyজিজ্ঞাসা করতে হয় IEnumerable.GetEnumerator, একটি দৃষ্টান্ত তৈরি করে এবং MoveNextকমপক্ষে একবার কল করে।

/ সম্পাদনা @ ম্যাট:

আমি কেবল ধরে নিতে পারি যে, গণনাকারীর জন্য গণনা () এক্সটেনশন পদ্ধতিটি এই জাতীয় কিছু করছে:

হ্যাঁ, অবশ্যই এটা আছে। এই আমি বোঝাতে চেয়েছিলাম। আসলে, এটি ICollectionপরিবর্তে ব্যবহার করে IListতবে ফলাফলটি একই।


6

আমি কেবল একটি দ্রুত পরীক্ষা লিখেছি, এটি চেষ্টা করুন:

 IEnumerable<Object> myList = new List<Object>();

 Stopwatch watch = new Stopwatch();

 int x;

 watch.Start();
 for (var i = 0; i <= 1000000; i++)
 {
    if (myList.Count() == 0) x = i; 
 }
 watch.Stop();

 Stopwatch watch2 = new Stopwatch();

 watch2.Start();
 for (var i = 0; i <= 1000000; i++)
 {
     if (!myList.Any()) x = i;
 }
 watch2.Stop();

 Console.WriteLine("myList.Count() = " + watch.ElapsedMilliseconds.ToString());
 Console.WriteLine("myList.Any() = " + watch2.ElapsedMilliseconds.ToString());
 Console.ReadLine();

দ্বিতীয়টি প্রায় তিনগুণ ধীর :)

স্ট্যাক বা অ্যারে বা অন্য পরিস্থিতিতে এটি স্টপওয়াচ পরীক্ষার সাথে আবার চেষ্টা করে দেখা যাচ্ছে যা দেখে মনে হয় তালিকার ধরণের উপর এটি নির্ভর করে - কারণ তারা গণনাটিকে ধীর বলে প্রমাণিত করে।

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

(কেবল উল্লেখ করার জন্য, আমি তালিকায় 2000+ অবজেক্ট রেখেছি এবং অন্যান্য ধরণের সাথে বিপরীতে গণনা এখনও দ্রুত ছিল)


12
Enumerable.Count<T>()জন্য বিশেষ হ্যান্ডলিং আছে ICollection<T>। আপনি যদি এটি একটি মৌলিক তালিকা ব্যতীত অন্য কিছু দিয়ে চেষ্টা করেন তবে আমি আশা করি আপনি উল্লেখযোগ্যভাবে পৃথক (ধীর) ফলাফল দেখতে পাবেন । Any()যদিও প্রায় একই থাকবে।
মার্ক গ্র্যাভেল

2
আমাকে মার্কের সাথে একমত হতে হবে; এটি সত্যিই সুষ্ঠু পরীক্ষা নয়।
ড্যান তাও

কোন ধারণা কেন বিশেষ হ্যান্ডলিং জন্য নয় Enumerable.Any<T>()জন্য ICollection<T>? অবশ্যই প্যারামিটারলেস খুব ভাল জন্য সম্পত্তি Any()পরীক্ষা করতে পারে ? CountICollection<T>
লুকাজয়েড

5

List.Countমাইক্রোসফ্টের ডকুমেন্টেশন অনুসারে ও (1):
http://msdn.microsoft.com/en-us/library/27b47ht3.aspx

সুতরাং এটি কেবল List.Count == 0একটি প্রশ্নের চেয়ে অনেক দ্রুত ব্যবহার করুন

এটি কারণ হিসাবে এটিতে ডেটা মেম্বার রয়েছে যা কাউন্ট নামক কোনও আপডেট রয়েছে যা তালিকা থেকে কিছু যোগ করা বা অপসারণের সময় আপডেট করা হয়, সুতরাং আপনি যখন কল করবেন তখন List.Countএটি পেতে প্রতিটি উপাদানকে পুনরাবৃত্তি করতে হবে না, এটি কেবল ডেটা সদস্যকে ফিরিয়ে দেয়।


1
যদি এটি "আইনিউমেবল" হয় তবে না no (সূচনাকারীদের জন্য আইনিম্যারেবলের "কাউন্ট" সম্পত্তি নেই, এটির একটি গণনা () পদ্ধতি রয়েছে।) "গণনা ()" কল করার জন্য তালিকার প্রতিটি একক উপাদান পরীক্ষা করার জন্য আইনিম্যারেবলের প্রয়োজন হবে। যদিও "যে কোনও" এটি 1 টি উপাদান খুঁজে পাওয়ার সাথে সাথে ফিরে আসবে।
00jt

এটি ডেটা উত্সের উপর নির্ভর করে। আপনি যদি কোনও আইইনিউমারেবল তৈরির জন্য ফলন ব্যবহার করেন তবে এটির আকার জানতে আইনুম্যারেবলকে অতিক্রম করতে হবে। সুতরাং এটি কিছু ক্ষেত্রে কেবল ও (1)। এটি সর্বদা ও (1) হয় না।
তমুসজেয়ার্স

3

আপনার যদি একাধিক আইটেম থাকে তবে দ্বিতীয় বিকল্পটি আরও দ্রুত।

  • Any() 1 টি আইটেম পাওয়া মাত্র ফিরে আসে।
  • Count() পুরো তালিকা দিয়ে যেতে হবে।

উদাহরণস্বরূপ ধরুন গণনার 1000 টি আইটেম ছিল।

  • Any() প্রথমটি পরীক্ষা করে দেখবে, তারপর সত্যে ফিরে আসবে।
  • Count() পুরো গণনাটি অনুসরণ করার পরে 1000 ফেরত আসবে।

আপনি সম্ভাব্য ওভাররাইডগুলির মধ্যে একটি ব্যবহার করলে এটি সম্ভাব্যতর খারাপ - গণনা () এখনও প্রতিটি একক আইটেম পরীক্ষা করতে হবে, এমনকি এটির জন্য কেবল একটি ম্যাচ রয়েছে।

আপনি যে কোনও একটি ব্যবহার করতে অভ্যস্ত হন - এটি কোনও অর্থপূর্ণ এবং পাঠযোগ্য and

একটি সতর্কতামূলক - যদি আপনার কাছে একটি তালিকা থাকে তবে কেবল একটি আইনামেরেবলের পরিবর্তে সেই তালিকার গণনা সম্পত্তিটি ব্যবহার করুন।


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

3

@ কনরাড যা আমাকে অবাক করে দিয়েছিল তা হচ্ছে আমার পরীক্ষাগুলিতে আমি তালিকাটিকে এমন কোনও পদ্ধতিতে পাস করি যা গ্রহণ করে IEnumerable<T>, তাই রানটাইমটি গণনা () এক্সটেনশন পদ্ধতিতে কল করে এটি অনুকূলিত করতে পারে না IList<T>

আমি কেবল ধরে নিতে পারি যে, গণনাকারীর জন্য গণনা () এক্সটেনশন পদ্ধতিটি এই জাতীয় কিছু করছে:

public static int Count<T>(this IEnumerable<T> list)
{
    if (list is IList<T>) return ((IList<T>)list).Count;

    int i = 0;
    foreach (var t in list) i++;
    return i;
}

... অন্য কথায়, এর বিশেষ ক্ষেত্রেটির জন্য কিছুটা রানটাইম অপ্টিমাইজেশন IList<T>

/ কনড্রেড +1 সাথী সম্পাদনা করুন - আপনি সম্ভবত এটি সম্পর্কে সম্ভবত ঠিক আছে ICollection<T>


1

ঠিক আছে, তাহলে এই সম্পর্কে কি?

public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
    return !enumerable.GetEnumerator().MoveNext();
}

সম্পাদনা: আমি ঠিক বুঝতে পেরেছি যে ইতিমধ্যে কেউ এই সমাধানটি স্কেচ করেছেন। এটি উল্লেখ করা হয়েছিল যে যে কোনও () পদ্ধতিটি এটি করবে, তবে কেন এটি নিজে করবেন না? শুভেচ্ছা সহ


3
তবে আপনি যখন এটি একটি usingব্লকে সঠিকভাবে আবদ্ধ করেন তখন এটি কম সংশ্লেষে পরিণত হয়, অন্যথায় আপনি কোনও IDisposableবস্তু তৈরি করেছেন এবং তারপরে এটি পরিত্যাগ করেছেন। তারপরে, অবশ্যই, আপনি যখন ইতিমধ্যে উপস্থিত এক্সটেনশন পদ্ধতিটি ব্যবহার করেন এবং এটি এটিকে পরিবর্তন করেন ( এটি অবিকল এটি করে) তখন এটি আরও সংক্ষিপ্ত হয়ে যায় return !enumerable.Any()
ড্যান তাও

ইতিমধ্যে একটি বিদ্যমান পদ্ধতি পুনর্লিখন কেন? উল্লিখিত হিসাবে Any()ঠিক এটি সম্পাদন করে, সুতরাং অন্য নামের সাথে একই পদ্ধতিটি যুক্ত করা বিভ্রান্তিকর হবে।
জুলিয়েন এন

1

আরেকটি ধারণা:

if(enumerable.FirstOrDefault() != null)

তবে আমি যে কোনও () পদ্ধতির চেয়ে বেশি পছন্দ করি।


3
যদি আপনার একটি খালি খালি তালিকা থাকে যেখানে প্রথম উপাদানটি বাতিল হয়?
ইকভু

1

সত্তা ফ্রেমওয়ার্কের সাথে এটি কাজ করা এটি সমালোচনামূলক ছিল:

var genericCollection = list as ICollection<T>;

if (genericCollection != null)
{
   //your code 
}

কিভাবে যে প্রশ্নের উত্তর দেয়? এর অভ্যন্তরে কোনও উপাদান না থাকায় সংগ্রহটি শূন্য হতে পারে না।
মার্টিন ভার্জানস

0

আমি যদি গণনা () লিনাকের সাথে চেক করি তবে ডাটাবেসে একটি "নির্বাচন করুন (*) .." চালিয়েছি তবে ফলাফলগুলিতে ডেটা রয়েছে কিনা তা যাচাই করা দরকার, আমি গণনা () এর পরিবর্তে ফার্স্টআরডিফল্ট () প্রবর্তন করার সিদ্ধান্ত নিয়েছি;

আগে

var cfop = from tabelaCFOPs in ERPDAOManager.GetTable<TabelaCFOPs>()

if (cfop.Count() > 0)
{
    var itemCfop = cfop.First();
    //....
}

পরে

var cfop = from tabelaCFOPs in ERPDAOManager.GetTable<TabelaCFOPs>()

var itemCfop = cfop.FirstOrDefault();

if (itemCfop != null)
{
    //....
}

0
private bool NullTest<T>(T[] list, string attribute)

    {
        bool status = false;
        if (list != null)
        {
            int flag = 0;
            var property = GetProperty(list.FirstOrDefault(), attribute);
            foreach (T obj in list)
            {
                if (property.GetValue(obj, null) == null)
                    flag++;
            }
            status = flag == 0 ? true : false;
        }
        return status;
    }


public PropertyInfo GetProperty<T>(T obj, string str)

    {
        Expression<Func<T, string, PropertyInfo>> GetProperty = (TypeObj, Column) => TypeObj.GetType().GetProperty(TypeObj
            .GetType().GetProperties().ToList()
            .Find(property => property.Name
            .ToLower() == Column
            .ToLower()).Name.ToString());
        return GetProperty.Compile()(obj, str);
    }

0

এখানে ড্যান টাওর উত্তরটির বাস্তবায়ন, একটি শিকারী হিসাবে অনুমতি দেওয়া:

public static bool IsEmpty<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null) throw new ArgumentNullException();
    if (IsCollectionAndEmpty(source)) return true;
    return !source.Any(predicate);
}

public static bool IsEmpty<TSource>(this IEnumerable<TSource> source)
{
    if (source == null) throw new ArgumentNullException();
    if (IsCollectionAndEmpty(source)) return true;
    return !source.Any();
}

private static bool IsCollectionAndEmpty<TSource>(IEnumerable<TSource> source)
{
    var genericCollection = source as ICollection<TSource>;
    if (genericCollection != null) return genericCollection.Count == 0;
    var nonGenericCollection = source as ICollection;
    if (nonGenericCollection != null) return nonGenericCollection.Count == 0;
    return false;
}


-3

myList.ToList().Count == 0। এখানেই শেষ


1
এটি একটি ভয়াবহ ধারণা। টোললিস্ট () অত্যধিক ব্যবহার করা উচিত নয়, কারণ এটি গণনাকারীদের পুরোপুরি মূল্যায়ন করতে বাধ্য করে। পরিবর্তে .এই () ব্যবহার করুন।
জন রিয়া

-5

এই এক্সটেনশন পদ্ধতিটি আমার পক্ষে কাজ করে:

public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
    try
    {
        enumerable.First();
        return false;
    }
    catch (InvalidOperationException)
    {
        return true;
    }
}

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

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

3
-1: আপনি যদি এইভাবে এটি করতে চান তবে চুলিওমার্টিনেজের উত্তরের মতো, ফার্স্টআরডিফল্ট () ব্যবহার করুন।
ড্যানিয়েল রোজ

3
ব্যতিক্রম হ্যান্ডলিংয়ের কার্যত দক্ষতার দক্ষতা নেই। সুতরাং এটি এখানে সবচেয়ে খারাপ সমাধান হতে পারে।
জুলিয়েন এন

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