লাইনকিউ .এই ভি ভি। এক্সজিস্টস - পার্থক্য কী?


413

সংগ্রহগুলিতে LINQ ব্যবহার করে, নিম্নলিখিত কোডের লাইনগুলির মধ্যে পার্থক্য কী?

if(!coll.Any(i => i.Value))

এবং

if(!coll.Exists(i => i.Value))

আপডেট 1

আমি বিচ্ছিন্ন করার .Existsসময় মনে হয় কোনও কোড নেই।

আপডেট 2

যে কেউ কেন জানেন যে এটির জন্য এখানে কোনও কোড নেই কেন?


9
আপনার সংকলিত কোডটি কেমন দেখাচ্ছে? আপনি কীভাবে বিচ্ছিন্ন করলেন? ildasm? আপনি কি প্রত্যাশা করেছিলেন তবে খুঁজে পাননি?
মেইনসবার

উত্তর:


423

ডকুমেন্টেশন দেখুন

তালিকাভুক্তকরণকারী (অবজেক্ট পদ্ধতি - এমএসডিএন)

তালিকায় (টি) এমন উপাদান রয়েছে যা নির্দিষ্ট প্রিকেট দ্বারা সংজ্ঞায়িত শর্তগুলির সাথে মেলে কিনা তা নির্ধারণ করে।

.NET 2.0 থেকে এটি বিদ্যমান, তাই লিনকিউ এর আগে। সম্পৃক্ত সঙ্গে ব্যবহার হতে বোঝানো প্রতিনিধি , কিন্তু ল্যামডা এক্সপ্রেশন অনগ্রসর সামঞ্জস্যপূর্ণ। এছাড়াও, কেবল তালিকার এটি রয়েছে (এমনকি আইলিস্টও নয়)

আইনিমেবল.এই (এক্সটেনশন পদ্ধতি - এমএসডিএন)

অনুক্রমের কোনও উপাদান কোনও শর্তকে সন্তুষ্ট করে কিনা তা নির্ধারণ করে।

এটি .NET 3.5 এ নতুন এবং ফানক (টিএসোর্স, বুল) যুক্তি হিসাবে ব্যবহার করে, তাই এটি ল্যাম্বডা এক্সপ্রেশন এবং লিনকিউ ব্যবহার করার উদ্দেশ্যে ছিল।

আচরণে, এগুলি অভিন্ন।


4
পরে আমি অন্য একটি থ্রেডে পোস্ট করেছি যেখানে আমি। নেট 2 List<>উদাহরণ পদ্ধতির সমস্ত লিঙ্ককে "সমতুল্য" তালিকাভুক্ত করেছি ।
জেপ্প স্টিগ নীলসন

201

পার্থক্যটি হ'ল যে IEnumerable<T>কোনওটি System.Linq.Eeumerable এর উপর সংজ্ঞায়িত কোনওর জন্য একটি এক্সটেনশন পদ্ধতি । এটি যে কোনও IEnumerable<T>পরিস্থিতিতে ব্যবহার করা যেতে পারে ।

অস্তিত্বগুলি কোনও এক্সটেনশন পদ্ধতি হিসাবে উপস্থিত হয় না। আমার অনুমান যে সংঘর্ষ টাইপ হয় List<T>। যদি তাই থাকে তবে একটি উদাহরণ পদ্ধতি যা কোনওটির সাথে খুব একই রকম কাজ করে।

সংক্ষেপে , পদ্ধতিগুলি মূলত একই রকম। একজন অন্যজনের চেয়ে বেশি সাধারণ।

  • যে কোনওটির একটি ওভারলোড রয়েছে যা কোনও পরামিতি নেয় না এবং কেবল গণনাযোগ্য কোনও আইটেম সন্ধান করে।
  • অস্তিত্বের এমন কোনও ওভারলোড নেই।

13
ভাল রাখুন (+1)। <T> তালিকা x তালিকা থেকে শুরু হয়েছে। নেট 2 তবে কেবল জেনেরিক তালিকার জন্য কাজ করে। অনুমানযোগ্য <টি> .একটি এক্সটেনশন হিসাবে নেট 3 এ যুক্ত করা হয়েছিল যে কোনও গণনাযোগ্য সংগ্রহে কাজ করে। তালিকার <T>। অ্যাকাউন্টের মতো একই সদস্য রয়েছে's
কিথ

51

TLDR; পারফরম্যান্স-অনুসারে Anyধীর বলে মনে হচ্ছে (যদি আমি প্রায় একই সময়ে উভয় মানকে মূল্যায়নের জন্য এটি সঠিকভাবে সেট আপ করি)

        var list1 = Generate(1000000);
        var forceListEval = list1.SingleOrDefault(o => o == "0123456789012");
        if (forceListEval != "sdsdf")
        {
            var s = string.Empty;
            var start2 = DateTime.Now;
            if (!list1.Exists(o => o == "0123456789012"))
            {
                var end2 = DateTime.Now;
                s += " Exists: " + end2.Subtract(start2);
            }

            var start1 = DateTime.Now;
            if (!list1.Any(o => o == "0123456789012"))
            {
                var end1 = DateTime.Now;
                s +=" Any: " +end1.Subtract(start1);
            }

            if (!s.Contains("sdfsd"))
            {

            }

পরীক্ষার তালিকা জেনারেটর:

private List<string> Generate(int count)
    {
        var list = new List<string>();
        for (int i = 0; i < count; i++)
        {
            list.Add( new string(
            Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                .Select(s =>
                {
                    var cryptoResult = new byte[4];
                    new RNGCryptoServiceProvider().GetBytes(cryptoResult);
                    return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                })
                .ToArray())); 
        }

        return list;
    }

10 এম রেকর্ড সহ

"যে কোনও: 00: 00: 00.3770377 বিদ্যমান: 00: 00: 00.2490249"

5M রেকর্ড সহ

"যে কোনও: 00: 00: 00.0940094 বিদ্যমান: 00: 00: 00.1420142"

1 এম রেকর্ড সহ

"যে কোনও: 00: 00: 00.0180018 বিদ্যমান: 00: 00: 00.0090009"

৫০০ কে দিয়ে, (প্রথমে কোনটিই চালিত হয় তার সাথে যুক্ত কোনও অতিরিক্ত ক্রিয়াকলাপ নেই কিনা তা দেখার জন্য তারা মূল্যায়ন করে যাতে ক্রম ঘুরে দেখলাম pped)

"বিদ্যমান: 00: 00: 00.0050005 যে কোনও: 00: 00: 00.0100010"

100k রেকর্ড সহ

"বিদ্যমান: 00: 00: 00.0010001 যে কোনও: 00: 00: 00.0020002"

এটি Any2 এর परिमाणের দ্বারা ধীর হয়ে যাবে বলে মনে হচ্ছে ।

সম্পাদনা করুন: 5 এবং 10 এম রেকর্ডের জন্য আমি তালিকাটি তৈরি করার পদ্ধতিটি পরিবর্তন করেছি এবং Existsহঠাৎ ধীর হয়ে গেছে Anyযার দ্বারা বোঝা যাচ্ছে যে আমি যা পরীক্ষা করছি তাতে কিছু ভুল আছে।

নতুন পরীক্ষার ব্যবস্থা:

private static IEnumerable<string> Generate(int count)
    {
        var cripto = new RNGCryptoServiceProvider();
        Func<string> getString = () => new string(
            Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                .Select(s =>
                {
                    var cryptoResult = new byte[4];
                    cripto.GetBytes(cryptoResult);
                    return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                })
                .ToArray());

        var list = new ConcurrentBag<string>();
        var x = Parallel.For(0, count, o => list.Add(getString()));
        return list;
    }

    private static void Test()
    {
        var list = Generate(10000000);
        var list1 = list.ToList();
        var forceListEval = list1.SingleOrDefault(o => o == "0123456789012");
        if (forceListEval != "sdsdf")
        {
            var s = string.Empty;

            var start1 = DateTime.Now;
            if (!list1.Any(o => o == "0123456789012"))
            {
                var end1 = DateTime.Now;
                s += " Any: " + end1.Subtract(start1);
            }

            var start2 = DateTime.Now;
            if (!list1.Exists(o => o == "0123456789012"))
            {
                var end2 = DateTime.Now;
                s += " Exists: " + end2.Subtract(start2);
            }

            if (!s.Contains("sdfsd"))
            {

            }
        }

সম্পাদনা 2: ঠিক আছে তাই পরীক্ষার ডেটা উত্পন্ন করার থেকে কোনও প্রভাব দূর করতে আমি এগুলি ফাইল করে লিখেছি এবং এখন সেখান থেকে এটি পড়ছি।

 private static void Test()
    {
        var list1 = File.ReadAllLines("test.txt").Take(500000).ToList();
        var forceListEval = list1.SingleOrDefault(o => o == "0123456789012");
        if (forceListEval != "sdsdf")
        {
            var s = string.Empty;
            var start1 = DateTime.Now;
            if (!list1.Any(o => o == "0123456789012"))
            {
                var end1 = DateTime.Now;
                s += " Any: " + end1.Subtract(start1);
            }

            var start2 = DateTime.Now;
            if (!list1.Exists(o => o == "0123456789012"))
            {
                var end2 = DateTime.Now;
                s += " Exists: " + end2.Subtract(start2);
            }

            if (!s.Contains("sdfsd"))
            {
            }
        }
    }

10M

"যে কোনও: 00: 00: 00.1640164 বিদ্যমান: 00: 00: 00.0750075"

5M

"যে কোনও: 00: 00: 00.0810081 বিদ্যমান: 00: 00: 00.0360036"

1 মি

"যে কোনও: 00: 00: 00.0190019 বিদ্যমান: 00: 00: 00.0070007"

500K

"যে কোনও: 00: 00: 00.0120012 বিদ্যমান: 00: 00: 00.0040004"

এখানে চিত্র বর্ণনা লিখুন


3
আপনার কাছে কোনও অমান্য নয়, তবে আমি এই মানদণ্ডগুলিতে সন্দেহের বোধ করছি। সংখ্যাগুলি দেখুন: প্রতিটি ফলাফলের পুনরাবৃত্তি ঘটে (3770377: 2490249)। কমপক্ষে আমার জন্য, এটি নিশ্চিত একটি চিহ্ন যা কিছু সঠিক নয়। আমি এখানে গণিতের উপর শতভাগ নিশ্চিত নই, তবে আমি মনে করি যে পুনরাবৃত্ত হওয়া প্যাটার্নটির অসুবিধাগুলি মূল্য অনুসারে 999 ^ 999 (বা 999! হতে পারে?) এর মধ্যে 1। সুতরাং এটি ঘটছে সম্ভাবনা 8 বার পরপর ক্ষুদ্রাতিক্ষুদ্র হয়। আমি মনে করি এটি কারণ আপনি বেঞ্চমার্কিংয়ের জন্য ডেটটাইম ব্যবহার করেন
জেরি কঙ্গাসনিয়েমি

@ জেরিক্যাঙ্গাসনিয়েমি বিচ্ছিন্নভাবে একই অপারেশনটির পুনরাবৃত্তি করতে সর্বদা একই পরিমাণ সময় নেওয়া উচিত, এটি একাধিকবার পুনরাবৃত্তি করতে চলেছে। আপনি কী বলে যে এটি ডেটটাইম?
মাতাস ভাইটকেভিচিয়াস

অবশ্যই আছে। সমস্যাটি এখনও রয়েছে যে 500k কলের জন্য 0120012 সেকেন্ডের উদাহরণ নেওয়া খুব বেশি সম্ভাবনা। এবং যদি এটি নিখুঁতভাবে রৈখিক হয়, সুতরাং সংখ্যাগুলি এত সুন্দরভাবে ব্যাখ্যা করে, 1 এম কলগুলি 0240024 সেকেন্ড (দ্বিগুণ দ্বিগুণ) গ্রহণ করেছিল, তবে এটি ক্ষেত্রে নয়। 1 এম কলগুলি 500k এর চেয়ে 58, (3)% বেশি সময় লাগে এবং 10M 5M এর চেয়ে 102,5% বেশি সময় নেয়। সুতরাং এটি কোনও লিনিয়ার ফাংশন নয় এবং এভাবে সমস্ত সংখ্যার পুনরাবৃত্তি হওয়া সংখ্যার পক্ষে সত্যই যুক্তিসঙ্গত নয়। আমি ডেটটাইম উল্লেখ করেছি কারণ অতীতে আমি নিজেই এর সাথে সমস্যায় পড়েছি ডেটটাইম উচ্চ নির্ভুলতা টাইমার ব্যবহার না করার কারণে।
জেরি কঙ্গাসনিয়েমি

2
@ জেরিক্যাঙ্গাস্নিমি আমি কি আপনাকে এটি ঠিক করার এবং একটি উত্তর পোস্ট করার পরামর্শ দিতে পারি
মাতাস ভাইটকেভিচিয়াস

1
আমি যদি আপনার ফলাফলগুলি সঠিকভাবে পড়ছি তবে আপনি কোনওটিকে অস্তিত্বের গতির চেয়ে 2 থেকে 3 গুণ বেশি বলে প্রতিবেদন করেছেন। আমি দেখতে পাই না যে কীভাবে ডেটা এমনকি আপনার দৃ 2়তার প্রতি সমর্থন করে যে "2 এর মাত্রার দ্বারা এটি ধীরে ধীরে হবে বলে মনে হয়" be এটি সামান্য ধীর, নিশ্চিত, মাত্রার অর্ডার নয়।
সানকাট 2000

16

বেঞ্চমার্কিংয়ে মাতাসের জবাবের ধারাবাহিকতা হিসাবে ।

টিএল / ডিআর : উপস্থিতি () এবং যে কোনও () সমান দ্রুত।

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

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

static void Main(string[] args)
    {
        Console.WriteLine("Generating list...");
        List<string> list = GenerateTestList(1000000);
        var s = string.Empty;

        Stopwatch sw;
        Stopwatch sw2;
        List<long> existsTimes = new List<long>();
        List<long> anyTimes = new List<long>();

        Console.WriteLine("Executing...");
        for (int j = 0; j < 1000; j++)
        {
            sw = Stopwatch.StartNew();
            if (!list.Exists(o => o == "0123456789012"))
            {
                sw.Stop();
                existsTimes.Add(sw.ElapsedTicks);
            }
        }

        for (int j = 0; j < 1000; j++)
        {
            sw2 = Stopwatch.StartNew();
            if (!list.Exists(o => o == "0123456789012"))
            {
                sw2.Stop();
                anyTimes.Add(sw2.ElapsedTicks);
            }
        }

        long existsFastest = existsTimes.Min();
        long anyFastest = anyTimes.Min();

        Console.WriteLine(string.Format("Fastest Exists() execution: {0} ticks\nFastest Any() execution: {1} ticks", existsFastest.ToString(), anyFastest.ToString()));
        Console.WriteLine("Benchmark finished. Press any key.");
        Console.ReadKey();
    }

    public static List<string> GenerateTestList(int count)
    {
        var list = new List<string>();
        for (int i = 0; i < count; i++)
        {
            Random r = new Random();
            int it = r.Next(0, 100);
            list.Add(new string('s', it));
        }
        return list;
    }

উপরের কোডটি 4 বার কার্যকর করার পরে (যা পরিবর্তে 1 000 করে Exists()এবং Any()1 000 000 উপাদানগুলির সাথে তালিকায় আসে), পদ্ধতিগুলি বেশ সমান দ্রুততর তা দেখতে অসুবিধা হবে না।

Fastest Exists() execution: 57881 ticks
Fastest Any() execution: 58272 ticks

Fastest Exists() execution: 58133 ticks
Fastest Any() execution: 58063 ticks

Fastest Exists() execution: 58482 ticks
Fastest Any() execution: 58982 ticks

Fastest Exists() execution: 57121 ticks
Fastest Any() execution: 57317 ticks

সেখানে হয় সামান্য পার্থক্য, কিন্তু এটা খুবই ছোট একটি পার্থক্য করতে আওয়াজকে দ্বারা ব্যাখ্যা করা যায়। আমার অনুমানটি হ'ল যদি কেউ 10 000 বা 100 000 করে Exists()এবং Any()তার পরিবর্তে, সামান্য পার্থক্য কমবেশি অদৃশ্য হয়ে যায়।


আমি কি আপনাকে 10 000 এবং 100 000 এবং 1000000 করার পরামর্শ দিতে পারি, এটি সম্পর্কে কেবল পদ্ধতিগত হতে, কেন ন্যূনতম এবং কেন গড় মূল্য নয়?
মাতাস ভাইটকেভিচিয়াস

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

আমি পল লিন্ডবার্গকে জিজ্ঞাসা করেছি এবং তিনি বলেছেন যে এটি ঠিক আছে;) ন্যূনতমতার ক্ষেত্রে আমি আপনার যুক্তি দেখতে পাচ্ছি তবে আরও গোঁড়া পদ্ধতির গড়পড়তা গড় ব্যবহার করা হচ্ছে en.wikedia.org/wiki/Algorithmic_e দক্ষতা# অনুশীলন
ম্যাটাস ভাইটকেভিচিয়াস

9
আপনি যে কোডটি পোস্ট করেছেন তা যদি আপনি প্রকৃত অর্পণ করেন তবে আপনি উভয় পরিমাপে অস্তিত্বকে কল করার সাথে সাথে একই ফলাফল পেয়ে অবাক হওয়ার কিছু নেই। ;)
সাইমন টাচটেক

হেই, হ্যাঁ, আমিও দেখেছি এখন আপনি এটি বলছেন। যদিও আমার ফাঁসি কার্যকর হয় না। এটি কেবল যা তুলনা করছি তার একটি প্রত্যাহার ধারণা হিসাবে বোঝানো হয়েছিল। : পি
জেরি কঙ্গাসনিমি

4

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


3

যখন আপনি পরিমাপগুলি সংশোধন করেন - উপরে উল্লিখিত হিসাবে: যে কোনও এবং বিদ্যমান এবং গড় যুক্ত - আমরা নিম্নলিখিত আউটপুটটি পেয়ে যাব:

Executing search Exists() 1000 times ... 
Average Exists(): 35566,023
Fastest Exists() execution: 32226 

Executing search Any() 1000 times ... 
Average Any(): 58852,435
Fastest Any() execution: 52269 ticks

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