2011-07-22 13 views
8

मैं निम्नलिखित सी # कोड लिखा है:मेरे लैम्ब्डा अभिव्यक्तियों को जल्दी मूल्यांकन करने के लिए कैसे मजबूर करें? लैम्ब्डा अभिव्यक्ति अजीबता को ठीक करें?

_locationsByRegion = new Dictionary<string, IEnumerable<string>>(); 
foreach (string regionId in regionIds) 
{ 
    IEnumerable<string> locationIds = Locations 
     .Where(location => location.regionId.ToUpper() == regionId.ToUpper()) 
     .Select(location => location.LocationId); //If I cast to an array here, it works. 
    _locationsByRegion.Add(regionId, LocationIdsIds); 
} 

इस कोड कुंजी और मूल्यों के रूप में "स्थान आईडी" की सूची के रूप में मेरे "क्षेत्र आईडी" के साथ एक एक शब्दकोश बनाने के लिए है।

हालांकि, वास्तव में क्या होता है कि मुझे "क्षेत्र आईडी" के साथ कुंजी के रूप में एक शब्दकोश मिलता है, लेकिन प्रत्येक कुंजी के लिए मान समान है: यह क्षेत्र आईडी में अंतिम क्षेत्र आईडी के लिए स्थानों की सूची है!

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

इस स्थिति को संभालने के लिए एक अच्छा अभ्यास क्या है?

+0

नहीं, यह एक पक्ष उत्पाद है - एक समय में बेहद उपयोगी पक्ष उत्पाद: इसके अलावा इस क्वेरी निष्पादित नहीं किया जाएगा जब तक आप, परिणाम तक पहुँचने का प्रयास या जब तक आप इसे शब्दकोश में बदलने का। – delnan

+0

एक तरफ ध्यान दें: आप या तो [Enumerable.Zip] (https://msdn.microsoft.com/en-us/library/dd267698 (v = vs.110) .aspx) या [गणना करने योग्य) को देखना चाहते हैं। ToDictionary] (https://msdn.microsoft.com/en-us/library/bb548657 (v = vs.110) .aspx) अपने लूप से छुटकारा पाने के लिए। –

उत्तर

10

आप LINQ का उपयोग कर रहे हैं। इसे करने के लिए आपको एक उत्सुक ऑपरेशन करने की आवश्यकता है। चयन करें। ToList() ऐसा करने के लिए एक अच्छा ऑपरेटर है। सूची सामान्य है इसे सीधे आईनंबरबल को असाइन किया जा सकता है।

यदि आप LINQ का उपयोग कर रहे हैं, तो यह डिफ़ॉल्ट रूप से आलसी मूल्यांकन करता है। Tolist/उत्सुक संचालन के लिए चुनने के लिए मजबूर बल। इन ऑपरेटरों में से किसी एक का उपयोग करने से पहले कार्रवाई नहीं की जाती है। यह ADO.NET प्रकार में एसक्यूएल निष्पादित करने जैसा है। यदि आपके पास "उपयोगकर्ताओं से * चुनें" कथन है जो वास्तव में क्वेरी नहीं करता है जब तक आप अतिरिक्त सामान नहीं करते। ToList चुनिंदा निष्पादन करता है।

+0

लालची ऑपरेटर क्या है? –

+0

@Rice इसका मतलब है कि कोई भी ऑपरेशन जो सेट, टोएरे, टोटल, ect की गणना करेगा। – asawyer

+0

उस मामले में जहां आप LINQ का उपयोग कर रहे हैं, यह डिफ़ॉल्ट रूप से आलसी मूल्यांकन करता है। ToList/लालची संचालन होने के लिए चयन बल। इन ऑपरेटरों में से किसी एक का उपयोग करने से पहले कार्रवाई नहीं की जाती है। यह ADO.NET प्रकार में एसक्यूएल निष्पादित करने जैसा है। यदि आपके पास "उपयोगकर्ताओं से * चुनें" कथन है जो वास्तव में क्वेरी नहीं करता है जब तक आप अतिरिक्त सामान नहीं करते। ToList चुनिंदा निष्पादन करता है। – m4tt1mus

4

Select(...) के बाद ToList() या ToArray() पर कॉल करें। इस प्रकार पूरे संग्रह का मूल्यांकन किया जाएगा।

+1

जैसा कि मैंने अपने प्रश्न में उल्लेख किया है, मैं 'ToArray()' को कॉल करने का प्रयास करता हूं और फिर इसे तुरंत एक गणना करने के लिए कास्टिंग करता हूं, लेकिन यह एक कड़वाहट की तरह लगता है। क्या कोई बेहतर तरीका है? –

+0

@ राइस आटा कुकीज़ और जैसे उन्होंने कहा, ToList() का उपयोग करें यह एक आईनेमरेबल है और इसके लिए कोई पुनरावृत्ति नहीं है। – m4tt1mus

+1

ठीक है, 'ToArray() 'भी' IENumerable' है। यह सिर्फ 'IENumerable 'नहीं है। लेकिन 'सूची ' 'IENumerable ' है। तो 'ToList() 'ठीक रहेगा। –

8

वैरिएबल पर आपका समापन, मूल्य नहीं।

_locationsByRegion = new Dictionary<string, IEnumerable<string>>(); 
foreach (string regionId in regionIds) 
{ 
    var regionToUpper = regionId.ToUpper(); 
    IEnumerable<string> locationIds = Locations 
     .Where(location => location.regionId.ToUpper() == regionToUpper) 
     .Select(location => location.LocationId); //If I cast to an array here, it works. 
    _locationsByRegion.Add(regionId, LocationIdsIds); 
} 

फिर इस पढ़ें:: - एक उत्सुक मूल्यांकन होगा जबरदस्ती

http://msdn.microsoft.com/en-us/vcsharp/hh264182

संपादित

ताकि आप के बजाय foreach पाश से वर्तमान मूल्य पर कब्जा चर की स्थानीय प्रतिलिपि बनाने दूसरों के सुझाव के रूप में भी काम करते हैं, लेकिन ज्यादातर समय उत्सुक मूल्यांकन बहुत धीमे होते हैं।

+0

को साफ़ करने के लिए धन्यवाद इस तरह से आप अभी भी आलसी मूल्यांकन कर रहे हैं। मैं निश्चित रूप से नहीं जान सकता, लेकिन ज्यादातर मामलों में यह केवल अतिरिक्त जटिलता है। इसके अलावा, यदि गणना के कुछ साइड इफेक्ट्स हैं - तो आप डिबगर में मान देखने पर आसानी से उन्हें ट्रिगर कर सकते हैं। यदि आपको आलसी मूल्यांकन की आवश्यकता नहीं है - इसका उपयोग न करें। खैर, यह प्रश्न लैम्ब्डा के शुरुआती मूल्यांकन के बारे में भी था। यह वही नहीं है जो आपने यहां सुझाया था। –

+0

@Ivan पोस्टर 'अजीबता' को ठीक करने के लिए जल्दी मूल्यांकन करना चाहता है, मैं यह इंगित कर रहा था कि वह ऐसा क्यों देख रहा था ताकि वह समझ सके कि वह जो व्यवहार देख रहा है उसके साथ क्या हो रहा है। – asawyer

+0

मैंने यह नहीं कहा कि यह -1 है। बस स्पष्ट किया कि शायद ओपी को उत्सुक मूल्यांकन की आवश्यकता है, सही बंद नहीं है। भले ही सही बंद काम करता है, उम ... सही :) –

0

असल सवाल देखने रचना है, जो मानक LINQ समूह के साथ सरल प्राप्त किया जा सकता है के बारे में में शामिल होने:

var query = from regionId in regionIds 
      join location in Locations 
      on regionId.ToLower() equals location.regionId.ToLower() into g 
      select new { RegionID = regionId, 
         Locations = g.Select(location => location.LocationId) }; 

इस मामले में सभी स्थानों के एक बार में डाउनलोड किया जाएगा, और इन-स्मृति वर्गीकृत किया। कैसे बंद कब्जा चर का -

var locationsByRegion = query.ToDictionary(x => x.RegionID, x => x.Locations); 
संबंधित मुद्दे