LINQ के साथ आदेश का संरक्षण


361

मैं ऑर्डर किए गए एरे पर ऑब्जेक्ट्स निर्देशों के लिए LINQ का उपयोग करता हूं। मुझे यह सुनिश्चित नहीं करना चाहिए कि सरणी का क्रम बदला नहीं गया है, मुझे कौन से संचालन करना चाहिए?

जवाबों:


645

मैंने System.Linq.Enumerable के तरीकों की जांच की , जो गैर-IEnumerable परिणाम लौटाता है। मैंने यह निर्धारित करने के लिए प्रत्येक की टिप्पणियों की जांच की कि परिणाम का क्रम स्रोत के आदेश से कैसे भिन्न होगा।

आदेश को पूरी तरह से संरक्षित करता है। आप किसी स्रोत तत्व को अनुक्रमणिका द्वारा परिणाम तत्व में मैप कर सकते हैं

  • AsEnumerable
  • कास्ट
  • concat
  • चुनते हैं
  • toArray
  • सूची बनाने के लिए

आदेश सुरक्षित रखता है। तत्वों को फ़िल्टर या जोड़ा जाता है, लेकिन फिर से आदेश नहीं दिया जाता है।

  • अलग
  • के सिवाय
  • इंटरसेक्ट
  • OfType
  • Prepend (नया .net 4.7.1 में)
  • छोड़ें
  • SkipWhile
  • लेना
  • TakeWhile
  • कहाँ पे
  • ज़िप (नया .net 4 में)

आदेश को नष्ट कर देता है - हम नहीं जानते कि किस क्रम में परिणाम की उम्मीद करनी चाहिए।

  • ToDictionary
  • देखने के लिए

Redefines ऑर्डर स्पष्ट रूप से - परिणाम के क्रम को बदलने के लिए इनका उपयोग करें

  • द्वारा आदेश
  • OrderByDescending
  • उलटना
  • तब तक
  • ThenByDescending

कुछ नियमों के अनुसार आदेश को फिर से परिभाषित करें।

  • GroupBy - IGrouping ऑब्जेक्ट्स को आदेश में तत्वों के क्रम के आधार पर प्राप्त किया जाता है, जो प्रत्येक IGrouping की पहली कुंजी का उत्पादन करता है। एक समूहीकरण में तत्वों का उत्पादन उस क्रम में किया जाता है जो वे स्रोत में दिखाई देते हैं।
  • GroupJoin - GroupJoin बाहरी के तत्वों के क्रम को बरकरार रखता है, और बाहरी के प्रत्येक तत्व के लिए, आंतरिक से मिलान तत्वों का क्रम।
  • सम्मिलित हों - बाहरी के तत्वों के क्रम को बरकरार रखता है, और इनमें से प्रत्येक तत्व के लिए, आंतरिक के मिलान तत्वों का क्रम।
  • SelectMany - स्रोत के प्रत्येक तत्व के लिए, चयनकर्ता को आमंत्रित किया जाता है और मूल्यों का एक अनुक्रम वापस किया जाता है।
  • संघ - जब इस विधि द्वारा लौटाए गए ऑब्जेक्ट को एन्यूमरेट किया जाता है, तो यूनियन उस क्रम में पहले और दूसरे स्थान पर गणना करता है और प्रत्येक तत्व की पैदावार करता है जो पहले से ही उपज नहीं हुआ है।

संपादित करें: मैंने इस कार्यान्वयन के आधार पर डिस्टिंक्ट को संरक्षित करने के आदेश में स्थानांतरित कर दिया है

    private static IEnumerable<TSource> DistinctIterator<TSource>
      (IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
    {
        Set<TSource> set = new Set<TSource>(comparer);
        foreach (TSource element in source)
            if (set.Add(element)) yield return element;
    }

2
इसलिए {1,2,1,3,1,3,4,1,5} होगा {1,2,3,4,5} - वास्तव में, मैं अलग बरकरार रखता है मूल (पहले पाया जाता है) आदेश लगता है
मार्क Gravell

10
msdn.microsoft.com/en-us/library/bb348436.aspx डिस्टिफ्ट <(<(TSource>)>) (IEnumerable <(<(TSource>)>))) विधि एक ऐसा अनियोजित क्रम देता है जिसमें कोई डुप्लिकेट मान नहीं होता है ।
एमी बी

12
मार्क: आप जो कहते हैं वह सच हो सकता है, लेकिन उस व्यवहार पर भरोसा करना एक बुरा विचार होगा।
एमी बी

4
@Amy B हां, लेकिन यह ऑब्जेक्ट्स पर Linq पर लागू नहीं होता है। Linq में Sql में, विशिष्ट () अलग कीवर्ड को उत्पन्न किए गए sql में डालता है, और sql से ऑर्डर करने की गारंटी नहीं है। मैं linq के लिए विशिष्ट वस्तुओं के कार्यान्वयन को देखना चाहूंगा जो ऑर्डर को संरक्षित नहीं करता है और अधिक कुशल है जो ऑर्डर को संरक्षित करता है। उदाहरण के लिए, आप पूरे इनपुट का उपभोग कर सकते हैं और इसे हैशसेट में डाल सकते हैं, फिर हैशसेट (ऑर्डर खोने) की गणना करके मान प्राप्त कर सकते हैं, लेकिन यह बदतर है। तो हाँ, मुझे हर बार और फिर :) दस्तावेज़ों को धता बताने में कोई आपत्ति नहीं है
dan

4
हो सकता है कि प्रलेखन ( Distinctविधि के लिए) का अर्थ केवल "अनसोल्ड" हो, न कि "अप्रत्याशित क्रम में"। मैं कहता हूं कि Distinctऊपर की तरह फ़िल्टरिंग श्रेणी से संबंधित है Where
जेपी स्टिग नीलसन

34

क्या आप वास्तव में SQL के बारे में, या सरणियों के बारे में बात कर रहे हैं? इसे दूसरे तरीके से रखने के लिए, क्या आप LINQ को SQL या LINQ को ऑब्जेक्ट्स में उपयोग कर रहे हैं?

ऑब्जेक्ट ऑपरेटर्स को LINQ वास्तव में उनके मूल डेटा स्रोत को परिवर्तित नहीं करता है - वे अनुक्रम बनाते हैं जो प्रभावी रूप से डेटा स्रोत द्वारा समर्थित होते हैं। ऑर्डरिंग को बदलने वाले एकमात्र ऑपरेशन ऑर्डरबाय / ऑर्डरबायस्केंडिंग / थेबी / तबबायस्केंडिंग - और फिर भी, समान रूप से ऑर्डर किए गए तत्वों के लिए स्थिर हैं। बेशक, कई ऑपरेशन कुछ तत्वों को फ़िल्टर करेंगे, लेकिन जो तत्व वापस आ जाएंगे, वे उसी क्रम में होंगे।

यदि आप एक अलग डेटा संरचना में कनवर्ट करते हैं, जैसे कि ToLookup या To मंदार के साथ, मेरा मानना ​​है कि आदेश उस बिंदु पर संरक्षित नहीं है - लेकिन यह वैसे भी कुछ अलग है। (मानों का क्रम उसी कुंजी पर मैप करने का क्रम लुकअप के लिए संरक्षित है, हालांकि मेरा मानना ​​है।)


इसलिए क्योंकि OrderBy एक स्थिर सॉर्ट है, तो: seq.OrderBy (_ => _.Key) तत्वों को बिल्कुल उसी क्रम में seq.GroupBy (_ => _.Key) के रूप में डाल देगा। SlectMany (_ => _)। )। क्या वो सही है?
dmg

1
@ एसडीएम: नहीं, यह नहीं होगा। बस GroupByइसके बाद SelectManyपरिणाम कुंजी द्वारा समूहीकृत होंगे, लेकिन आरोही कुंजी क्रम में नहीं ... यह उन्हें उस क्रम में देगा जिसमें कुंजी मूल रूप से हुई थी।
जॉन स्कीट

क्या आप कह रहे हैं कि LINQ to SQL प्रेज़रवर ऑर्डर नहीं करता है?
सहजीवन

@symbiont: कई एसक्यूएल संचालन में वहाँ है कोई अच्छी तरह से परिभाषित आदेश के साथ शुरू करने के लिए। मूल रूप से मैं केवल उन चीजों के बारे में वादे करने की कोशिश कर रहा हूं जिनकी मैं गारंटी दे सकता हूं - जैसे कि LINQ ऑब्जेक्ट्स के लिए।
जॉन स्कीट

@JonSkeet यदि मैं ऑर्डरबाई का उपयोग करता हूं तो यह गारंटी देता है कि एक ही कुंजी के साथ 'एन' ऑब्जेक्ट उनके मूल अनुक्रम को संरक्षित करेंगे सिवाय इसके कि वे सभी एक साथ हों। ie.: list<x> {a b c d e f g}यदि c, d, e सभी में समान कुंजी है तो परिणामी अनुक्रम में c, d, e एक दूसरे के बगल में और आदेश c, d, e में होंगे। मुझे एक स्पष्ट MS- आधारित उत्तर नहीं मिल रहा है।
पॉलिसियस

7

यदि आप किसी सरणी पर काम कर रहे हैं, तो ऐसा लगता है कि आप LINQ-to-Objects का उपयोग कर रहे हैं, SQL का नहीं; क्या आप पुष्टि कर सकते हैं? अधिकांश LINQ ऑपरेशंस किसी भी चीज़ को री-ऑर्डर नहीं करते हैं (आउटपुट इनपुट के समान ऑर्डर में होगा) - इसलिए किसी अन्य प्रकार (ऑर्डरबाय [अवरोही] / फिर तब तक लागू न करें] पर लागू न करें)।

[संपादित करें: जॉन ने और अधिक स्पष्ट रूप से कहा; LINQ आम तौर पर एक नया अनुक्रम बनाता है , जो मूल डेटा को अकेला छोड़ देता है]

ध्यान दें कि डेटा को एक Dictionary<,>(To मंदार) में धकेलने से डेटा खराब हो जाएगा, क्योंकि शब्दकोश किसी विशेष प्रकार के आदेश का सम्मान नहीं करता है।

लेकिन ज्यादातर सामान्य चीजें (सेलेक्ट, व्हेयर, स्किप, टेक) ठीक होनी चाहिए।


अगर मैं गलत नहीं हूं, तो ToDictionary()केवल ऑर्डर के बारे में कोई वादा नहीं करता , लेकिन व्यवहार में इनपुट ऑर्डर बनाए रखता है (जब तक कि आप इसमें से कुछ नहीं निकालते)। मैं इस पर भरोसा करने के लिए नहीं कह रहा हूं, लेकिन 'हाथापाई' गलत है।
टिमो

4

मुझे इसी तरह के प्रश्न में एक महान जवाब मिला जो आधिकारिक दस्तावेज का संदर्भ देता है। इसे उद्धृत करने के लिए:

के लिए Enumerableतरीके (वस्तुओं को LINQ, पर लागू होता है जो List<T>), आप द्वारा दिया तत्वों के आदेश पर भरोसा कर सकते हैं Select, Whereया GroupBy। यह उन चीज़ों के लिए नहीं है जो स्वाभाविक रूप से अनियंत्रित हैं जैसे ToDictionaryया Distinct

से Enumerable.GroupBy प्रलेखन:

प्रत्येक IGrouping<TKey, TElement>स्रोत की पहली कुंजी उत्पन्न करने वाले स्रोत में तत्वों के क्रम के आधार पर वस्तुओं का उत्पादन किया जाता है IGrouping<TKey, TElement>। एक समूहीकरण में तत्वों को उस क्रम में प्राप्त किया जाता है जिस क्रम में वे दिखाई देते हैं source

यह जरूरी नहीं कि IQueryableविस्तार के तरीकों (अन्य LINQ प्रदाताओं) के लिए सही हो।

स्रोत: LINQ के अनगिनत तरीके तत्वों के सापेक्ष क्रम को बनाए रखते हैं?


2

कोई भी 'समूह' या 'क्रम से' संभवतः आदेश को बदल देगा।


0

यहाँ प्रश्न विशेष रूप से LINQ-to-Objects का जिक्र कर रहा है।

यदि आपके बजाय LINQ-to-SQL का उपयोग कर रहा है तो वहां कोई आदेश नहीं है जब तक कि आप एक को कुछ के साथ नहीं लगाते हैं:

mysqlresult.OrderBy(e=>e.SomeColumn)

यदि आप LINQ-to-SQL के साथ ऐसा नहीं करते हैं, तो परिणाम का क्रम बाद के प्रश्नों के बीच भिन्न हो सकता है, यहां तक ​​कि समान डेटा के कारण, जो आंतरायिक बग पैदा कर सकता है।

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