LINQ: सभी बनाम कोई नहीं


272

अक्सर मैं जांचना चाहता हूं कि क्या एक प्रदान की गई सूची में एक से मेल खाता है (उदाहरण के लिए जब सत्यापन):

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

हाल ही में, मैंने देखा है कि ReSharper ने मुझे इन प्रश्नों को सरल बनाने के लिए कहा:

if (acceptedValues.All(v => v != someValue))
{
    // exception logic
}

जाहिर है, यह तार्किक रूप से समान है, शायद थोड़ा अधिक पठनीय (यदि आपने बहुत गणित किया है), मेरा सवाल यह है: क्या यह एक प्रदर्शन हिट है?

ऐसा लगता है कि ( .Any()जैसे यह शॉर्ट-सर्किट की .All()तरह लगता है , जबकि ऐसा लगता है) ऐसा नहीं है, लेकिन मुझे इस बात को पुष्ट करने के लिए कुछ भी नहीं है। क्या किसी के पास गहन ज्ञान है कि क्या प्रश्न वही हल करेंगे, या क्या ReSharper मुझे भटका रहा है?


6
क्या आपने देखा है कि यह क्या कर रहा है यह देखने के लिए Linq कोड को अलग करने की कोशिश की?
RQDQ

9
इस मामले में मैं वास्तव में अगर ((!VVues.Contains (someValue)) स्वीकार करता हूं, लेकिन निश्चित रूप से यह सवाल नहीं था :)
csgero

2
@csgero मैं सहमत हूं। ऊपर वास्तविक तर्क का एक सरलीकरण (शायद अति-सरलीकरण) था।
मार्क

1
"ऐसा लगता है कि इसे (यानी। किसी को भी) यह शॉर्ट-सर्किट की तरह लगता है, जबकि। (सभी को ऐसा लगता है) नहीं" - ध्वनि अंतर्ज्ञान वाले किसी को भी नहीं। आपके द्वारा नोट किए गए तार्किक समानता का तात्पर्य है कि वे समान रूप से लघु-संक्रमणीय हैं। एक पल के विचार से पता चलता है कि सभी गैर-योग्यता वाले मामले का सामना करते ही छोड़ सकते हैं।
जिम बैटर

3
मैं इस पर ReSharper के साथ सार्वभौमिक रूप से सहमत नहीं हूं। विचार की समझदार गाड़ियों को लिखें। यदि आप एक अपवाद फेंकना चाहते हैं यदि एक आवश्यक वस्तु गायब है if (!sequence.Any(v => v == true)):। यदि आप केवल तभी जारी रखना चाहते हैं जब सब कुछ एक निश्चित विनिर्देश के अनुरूप हो if (sequence.All(v => v < 10)):।
टिमो

जवाबों:


344

AllILSpy के अनुसार कार्यान्वयन (जैसा कि मैंने वास्तव में देखा और देखा, "अच्छी तरह से होने के बजाय, यह तरीका थोड़ा काम करता है ..." मैं कर सकता हूं अगर हम प्रभाव के बजाय सिद्धांत पर चर्चा कर रहे थे)।

public static bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    foreach (TSource current in source)
    {
        if (!predicate(current))
        {
            return false;
        }
    }
    return true;
}

AnyILSpy के अनुसार कार्यान्वयन :

public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    foreach (TSource current in source)
    {
        if (predicate(current))
        {
            return true;
        }
    }
    return false;
}

बेशक, उत्पादित आईएल में कुछ सूक्ष्म अंतर हो सकता है। लेकिन नहीं, नहीं वहाँ नहीं है। IL बहुत अधिक समान है, लेकिन विधेय मिलान पर सच लौटने के स्पष्ट उलट के लिए बनाम विधेय बेमेल पर झूठे लौटने के लिए।

यह केवल पाठ्यक्रम के लिए linq-for-Objects है। यह संभव है कि कुछ अन्य linq प्रदाता एक दूसरे की तुलना में बहुत बेहतर व्यवहार करते हैं, लेकिन फिर अगर ऐसा होता, तो यह बहुत अधिक यादृच्छिक होता है, जिसे अधिक इष्टतम कार्यान्वयन मिला।

ऐसा लगता है कि यह नियम पूरी तरह से किसी को लग रहा है कि if(determineSomethingTrue)यह सरल और अधिक पठनीय है if(!determineSomethingFalse)। और निष्पक्षता में, मुझे लगता है कि उनके पास एक बिंदु है जिसमें मैं अक्सर if(!someTest)भ्रमित हो जाता हूं * जब समान क्रियाशीलता और जटिलता का एक वैकल्पिक परीक्षण होता है जो उस स्थिति के लिए सही होता है जिस पर हम कार्य करना चाहते हैं। फिर भी वास्तव में, मैं व्यक्तिगत रूप से आपके द्वारा दिए गए दो विकल्पों में से एक के पक्ष में एक का पक्ष लेने के लिए कुछ भी नहीं पाता हूं, और शायद यह पूर्व की ओर बहुत थोड़ा झुक जाएगा यदि विधेय अधिक जटिल था।

* जैसा कि मुझे समझ में नहीं आ रहा है, वैसे ही भ्रमित करना, लेकिन जैसा कि मुझे चिंता है कि निर्णय के कुछ सूक्ष्म कारण हैं जो मुझे समझ में नहीं आते हैं, और यह महसूस करने के लिए कुछ मानसिक झोंके लगते हैं कि "नहीं, उन्होंने बस करने का फैसला किया इस तरह, प्रतीक्षा करें कि मैं इस कोड को फिर से क्या देख रहा था? ... "


8
मुझे यकीन नहीं है कि लाइनों के पीछे क्या किया जाता है, लेकिन मेरे लिए बहुत अधिक पठनीय है: अगर (किसी भी नहीं) की तुलना में अगर (सभी बराबर नहीं)।
VikciaR

49
जब आपकी गणना का कोई मूल्य नहीं है, तो एक बड़ा अंतर होता है। 'कोई' हमेशा FALSE लौटाएगा, और 'सभी' हमेशा TRUE लौटाएगा। इसलिए एक से दूसरे का तार्किक बराबर कहना पूरी तरह सत्य नहीं है!
अरनौद

44
@ अरनॉड Anyवापस आएगा falseऔर इसलिए !Anyवापस आएगा true, इसलिए वे समान हैं।
जॉन हैना

11
@ अरनॉड कोई भी व्यक्ति नहीं है जिसने टिप्पणी की कि किसने कहा कि कोई भी और सभी तार्किक रूप से समान हैं। या इसे दूसरे तरीके से रखने के लिए, टिप्पणी करने वाले सभी व्यक्तियों ने यह नहीं कहा कि कोई भी और सभी तार्किक रूप से समान हैं। समतुल्य के बीच है! कोई भी (विधेय) और सभी (विधेय)।
जिम बाल्टर 20'13

7
@MacsDickinson बिल्कुल भी अंतर नहीं है, क्योंकि आप विपरीत भविष्यवाणी की तुलना नहीं कर रहे हैं। के बराबर !test.Any(x => x.Key == 3 && x.Value == 1)है कि का उपयोग करता है Allहै test.All(x => !(x.Key == 3 && x.Value == 1))(जो वास्तव में के बराबर है test.All(x => x.Key != 3 || x.Value != 1))।
जॉन हैना 14

55

आप पा सकते हैं कि ये विस्तार विधियाँ आपके कोड को अधिक पठनीय बनाती हैं:

public static bool None<TSource>(this IEnumerable<TSource> source)
{
    return !source.Any();
}

public static bool None<TSource>(this IEnumerable<TSource> source, 
                                 Func<TSource, bool> predicate)
{
    return !source.Any(predicate);
}

अब अपने मूल के बजाय

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

तुम कह सकते हो

if (acceptedValues.None(v => v == someValue))
{
    // exception logic
}

6
धन्यवाद - मैं पहले से ही हमारे कॉमन्स लाइब्रेरी में इन्हें लागू करने के बारे में सोच रहा था, लेकिन मैंने अभी तक यह तय नहीं किया है कि यह एक अच्छा विचार है। मैं सहमत हूं कि वे कोड को अधिक पठनीय बनाते हैं, लेकिन मुझे चिंता है कि वे पर्याप्त मूल्य नहीं जोड़ते हैं।
मार्क

2
मैंने किसी को नहीं देखा और वह नहीं मिला। यह बहुत अधिक पठनीय है।
कर्क

मुझे null चेक्स जोड़ना था: रिटर्न सोर्स == null || ! source.Any (विधेय);
कर्क राशि

27

दोनों का समान प्रदर्शन होगा क्योंकि दोनों परिणाम के बाद गणना को रोक सकते हैं - Any()पहले आइटम पर पारित विधेय का मूल्यांकन करता है trueऔर All()पहले आइटम पर विधेय का मूल्यांकन करता है false


21

All पहले गैर-मैच पर शॉर्ट सर्किट, तो यह कोई समस्या नहीं है।

सूक्ष्मता का एक क्षेत्र वह है

 bool allEven = Enumerable.Empty<int>().All(i => i % 2 == 0); 

सच हैं। अनुक्रम में सभी आइटम यहां तक ​​कि हैं।

इस पद्धति पर अधिक जानकारी के लिए, Enumerable.All के लिए प्रलेखन से परामर्श करें ।


12
हां, लेकिन bool allEven = !Enumerable.Empty<int>().Any(i => i % 2 != 0)सच भी है।
जॉन हन्ना

1
@ जून शब्दार्थ! कोई नहीं! इसलिए शब्दशः आपके पास या तो कोई भी नहीं है लेकिन सभी के मामले में। सभी () में से कोई भी केवल उन सभी संग्रहों का उपसमूह नहीं है जो सभी के लिए सही हैं और यदि आप इसके बारे में अनजान हैं तो विसंगति हो सकती है। एंथनी के लिए +1
रुण एफएस

@RuneFS मैं अनुसरण नहीं करता। शब्दार्थ और तार्किक रूप से "कोई नहीं जहां यह असत्य है कि ..." वास्तव में "सभी जहां यह सत्य है" के समान है। उदा "जहां हमारी कंपनी से स्वीकृत परियोजनाओं में से कोई भी नहीं है?" हमेशा "जहां सभी अन्य कंपनियों से स्वीकृत परियोजनाओं के सभी के रूप में एक ही जवाब होगा?" ...
जॉन हैना

... अब, यह सच है कि आप "सभी आइटम हैं ..." मानने से कीड़े हो सकते हैं, इसका मतलब है कि कम से कम एक आइटम कम से कम एक आइटम है जो परीक्षण को पूरा करता है, क्योंकि "सभी आइटम ... "हमेशा खाली सेट के लिए सच है, मैं उस पर विवाद नहीं करता हूं। मैंने हालांकि यह भी कहा कि "कोई भी आइटम नहीं ..." मानने के साथ एक ही समस्या हो सकती है, इसका मतलब है कि कम से कम एक आइटम परीक्षण पूरा नहीं करता है, क्योंकि "कोई भी आइटम नहीं ..." हमेशा खाली सेट के लिए भी सही है। । ऐसा नहीं है कि मैं एंथनी की बात से असहमत हूं, इसकी यह है कि मुझे लगता है कि यह चर्चा के तहत दो निर्माणों में से एक के लिए भी है।
जॉन हन्ना

@ आप तर्क की बात कर रहे हैं और मैं भाषाविज्ञान की बात कर रहा हूं। मानव मस्तिष्क एक नकारात्मक प्रक्रिया नहीं कर सकता है (इससे पहले कि यह सकारात्मक प्रक्रिया जिस बिंदु पर यह फिर इसे नकारात्मक कर सकता है) उस अर्थ में दोनों के बीच काफी अंतर है। वह तर्क गलत नहीं करता है जिसे आप गलत प्रस्तावित करते हैं
Rune FS

8

All()यह निर्धारित करता है कि क्या अनुक्रम के सभी तत्व किसी स्थिति को संतुष्ट करते हैं।
Any()निर्धारित करता है कि किसी अनुक्रम का कोई तत्व स्थिति को संतुष्ट करता है या नहीं।

var numbers = new[]{1,2,3};

numbers.All(n => n % 2 == 0); // returns false
numbers.Any(n => n % 2 == 0); // returns true

7

इस लिंक के अनुसार

कोई भी - कम से कम एक मैच के लिए जाँच

ऑल - चेक कि सभी मैच


1
आप सही हैं, लेकिन वे किसी दिए गए संग्रह के लिए उसी समय रुक जाते हैं। जब स्थिति विफल हो जाती है तो सभी टूट जाते हैं और जब यह आपके विधेय से मेल खाता है तो कोई भी ब्रेक। तो तकनीकी रूप से अलग नहीं है सिवाय स्वाभाविक रूप से
WPFKK

6

जैसा कि अन्य उत्तर अच्छी तरह से कवर कर चुके हैं: यह प्रदर्शन के बारे में नहीं है, यह स्पष्टता के बारे में है।

आपके दोनों विकल्पों के लिए व्यापक समर्थन है:

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

if (acceptedValues.All(v => v != someValue))
{
    // exception logic
}

लेकिन मुझे लगता है कि इससे व्यापक समर्थन मिल सकता है :

var isValueAccepted = acceptedValues.Any(v => v == someValue);
if (!isValueAccepted)
{
    // exception logic
}

बस कुछ भी नकारने से पहले बूलियन (और इसका नामकरण) की गणना करना मेरे दिमाग में बहुत कुछ साफ करता है।


3

यदि आप Enumerable स्रोत पर एक नज़र डालते हैं तो आप देखेंगे कि इसका कार्यान्वयन Anyऔर Allकाफी करीब है:

public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
    if (source == null) throw Error.ArgumentNull("source");
    if (predicate == null) throw Error.ArgumentNull("predicate");
    foreach (TSource element in source) {
        if (predicate(element)) return true;
    }
    return false;
}

public static bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
    if (source == null) throw Error.ArgumentNull("source");
    if (predicate == null) throw Error.ArgumentNull("predicate");
    foreach (TSource element in source) {
        if (!predicate(element)) return false;
    }
    return true;
}

कोई तरीका नहीं है कि एक विधि दूसरे की तुलना में काफी तेज हो क्योंकि एकमात्र अंतर एक बूलियन नकार में निहित है, इसलिए झूठी प्रदर्शन जीत पर पठनीयता पसंद करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.