erlang

2011-01-23 17 views
9

में किसी सूची में तत्व को कैसे बदलें, मेरे पास एक सूची है जिसे मैंने फ़ंक्शन सूचियों का उपयोग किया है: nth() किसी निश्चित अनुक्रमणिका पर किसी तत्व के मान को वापस करने के लिए। क्या कोई जानता है कि मैं इस मूल्य को कैसे संपादित कर सकता हूं?erlang

किसी भी मदद महान

धन्यवाद

मार्क होगा।

संपादित करें: यहां कुछ और जानकारी है। कहो मैं एक सूची एल जो एक पाठ आधारित ग्रिड

L = [H,H,H,H,H]. 

की एक पंक्ति का प्रतिनिधित्व करता था और मैं एक निर्दिष्ट तत्व उदाहरण तीसरे एक के लिए कहते हैं और ई के लिए यह तो बदल अगर मैं का उपयोग किया गया उपयोग करना चाहते सूची एल फिर यह होगा

[H,H,E,H,H]

मुझे आशा है कि यह अधिक समझ में आता है।

धन्यवाद।

+0

मैंने हाल ही में इस सटीक प्रश्न से पूछा: http://stackoverflow.com/questions/4370756/replace-an-element-at-an-index-in-a-list-in-erlang – MatthewToday

उत्तर

17

एक सूची अपरिवर्तनीय है, इसलिए आप सूची में किसी आइटम को "बदल नहीं सकते"। क्या तुम सच में किसी विशिष्ट स्थान पर एक आइटम को बदलना चाहते हैं, तो आप (परिवर्तित) तत्व के साथ तत्व और शेष सूची से पहले सूची संलग्न करना होगा:

1> L=[1,2,3,4,5]. 
[1,2,3,4,5] 
2> lists:sublist(L,2) ++ [lists:nth(3,L)*100] ++ lists:nthtail(3,L). 
[1,2,300,4,5] 

संपादित करें: परिदृश्य थोड़ा असामान्य है, हालांकि है। .. क्या आपके पास हाथ में एक विशिष्ट समस्या है? शायद इसे बेहतर के साथ व्यक्त किया जा सकता है एक सूचियां: नक्शा?

+0

कहता है कि मेरे पास सूची एल थी = [एच, एच, एच, एच, एच]। और मैं तीसरे तत्व को ई – MulletDevil

+2

इंडेक्स = 3 में बदलना चाहता था। सूचियां: sublist (एल, सूचकांक -1) ++ "ई" ++ सूचियां: nthtail (सूचकांक, एल)। –

3

सूचियों के साथ काम करते समय सभी तत्व अक्सर समान डेटाटाइप या अर्थ के होते हैं। आप शायद ही कभी ["John Doe","1970-01-01","London"] जैसी सूचियां देखें लेकिन #person{name="John Doe",...} या यहां तक ​​कि {"जॉन डो", ...}। रिकॉर्ड और टुपल में मान बदलने के लिए:

यह आपकी विशेष समस्या के लिए कुछ भी हल नहीं कर सकता है। टिप्पणी में अपने खुद के उदाहरण लेते हैं:

f1([H1,H2,_H3,H4,H5],E) -> [H1,H2,E,H4,H5]. 

आप पर्यावरण और समस्या यह है जिसके तहत समाधान सबसे अच्छा काम हो सकता है आसान है के एक अधिक विशिष्ट विवरण दे रहे हैं।

संपादित करें: एक (बल्कि बुरा) समाधान 1.

replacenth(L,Index,NewValue) -> 
{L1,[_|L2]} = lists:split(Index-1,L), 
L1++[NewValue|L2]. 

1> replacenth([1,2,3,4,5],3,foo). 
[1,2,foo,4,5] 

या थोड़ा अधिक कुशल अपनी सूची की लंबाई के आधार।

replacenth(Index,Value,List) -> 
replacenth(Index-1,Value,List,[],0). 

replacenth(ReplaceIndex,Value,[_|List],Acc,ReplaceIndex) -> 
lists:reverse(Acc)++[Value|List]; 
replacenth(ReplaceIndex,Value,[V|List],Acc,Index) -> 
replacenth(ReplaceIndex,Value,List,[V|Acc],Index+1). 

और भी बेहतर से ऊपर लेकिन शायद मेरी समारोह f1, बस शायद समस्या अभी भी स्थित है, जैसा कि ऊपर या here पर चर्चा की है।

+0

मैंने अधिक जानकारी प्रदान करने के लिए प्रश्न संपादित किया। आशा है कि ये आपकी मदद करेगा। धन्यवाद। – MulletDevil

11

lists से कार्यों का उपयोग कर कोड लगता है कि स्पष्ट यह तत्वों की सूची से पहले तत्व आप बदलना चाहते हैं दो बार कॉपी किया जाएगा के रूप में कम कुशल है में हो सकता है है। फ़ंक्शन को स्वयं लिखना अधिक कुशल है, और जैसा कि आप शायद किसी फ़ंक्शन में lists का उपयोग करके कोड को लपेटेंगे, मुझे नहीं लगता कि यह कम स्पष्ट होगा।

@ डी द्वारा कोड के बजाय।निबॉन मैं इस समारोह को लिखूंगा:

%% setnth(Index, List, NewElement) -> List. 

setnth(1, [_|Rest], New) -> [New|Rest]; 
setnth(I, [E|Rest], New) -> [E|setnth(I-1, Rest, New)]. 

%% Can add following caluse if you want to be kind and allow invalid indexes. 
%% I wouldn't! 
%% setnth(_, [], New) -> New. 

तर्क आदेश पर चर्चा की जा सकती है; दुर्भाग्यवश lists मॉड्यूल यहां कोई मदद नहीं है क्योंकि यह मॉड्यूल के भीतर असंगत है। हालांकि यह पूंछ-पुनरावर्ती कार्य नहीं है, मुझे लगता है कि यह स्पष्ट है। दक्षता में अंतर छोटा या अस्तित्वहीन है इसलिए मैं स्पष्टता के साथ जाऊंगा। इस समस्या के बारे में अधिक जानकारी के लिए देखें:

http://www.erlang.org/doc/efficiency_guide/myths.html#tail_recursive
http://www.erlang.org/doc/efficiency_guide/listHandling.html#id64759

एक अधिक बहुमुखी समारोह के लिए बजाय सिर्फ नए मूल्य की आप एक fun जो पुराने मूल्य के साथ कहा जा सकता है गुजरती हैं और नया मान लौट सकते हैं। एक पुस्तकालय में शायद मैं दोनों होगा।

3
L = [H,H,H,H,H]. 

और मैं इसे फिर से किया जाएगा तक पहुँचने के लिए एक निर्दिष्ट तत्व उदाहरण तीसरे एक के लिए कहते हैं और ई के लिए यह तो बदल अगर मैं सूची एल का इस्तेमाल किया गया चाहते

[H,H,E,H,H] 

एक वास्तविक नाइटपिकर होने के लिए। Erlang में, डेटा लगातार और अपरिवर्तनीय हैं। एक बार जब आप L = ... भाग को परिभाषित कर लेंगे, L पत्थर में सेट है। आप इसे वहां से नहीं बदल सकते हैं। आप क्या कर सकते हैं एक नया मान बनाना और इसे दूसरे चर में बांधना, L1 कहें और फिर L का उपयोग करना बंद करें। कचरा कलेक्टर तुरंत L का संक्षिप्त काम करेगा और इसका इस्तेमाल स्मृति की रीसायकल करेगा।

इसलिए, यह कहना गलत है कि L का उपयोग करके इसकी सामग्री बदल जाती है, क्योंकि यह असंभव है।

उल्लेख करने का एक और बिंदु यह है कि यदि आप सूची का उपयोग करते हैं जैसे कि यह एक सरणी है, तो आप एक सरणी (array मॉड्यूल से) का उपयोग कर सकते हैं या एक dict (dict मॉड्यूल से) का उपयोग कर सकते हैं। यह आपके मामले में लुकअप और अपडेट की गति को काफी बढ़ाता है। यदि आप सबसे ज्यादा करते हैं तो सभी तत्वों पर संसाधित करने के लिए सूची का ट्रैवर्सल होता है, हालांकि, सूची शायद विजेता बनने जा रही है।

-1
1> lists:reverse(element(2, lists:foldl(fun(E, {I, L}) -> {I + 1, [case I of 2 -> e; _ -> E end|L]} end, {0, []}, [h,h,h,h,h]))). 

[h,h,e,h,h] 

सुंदर नहीं है लेकिन मैं शर्त काफी कुशल हूं।

+0

एक ही नस में एक विकल्प 'मजेदार (आर, एन, एल) -> केस सूचियां: {एफ, [_ | टी]} के विभाजन (एन -1, एल) -> एफ ++ [आर | टी] अंत अंत (ई, 3, [एच, एच, एच, एच, एच]) ', लेकिन कुशल, इन कार्यान्वयन नहीं हैं, जब तक कि सूची काफी छोटी न हो। –

+0

वाह, सूचियों का एहसास नहीं हुआ: मानचित्र/फ़ोल्डल सूचियों की तुलना में धीमी गति से धीमा है: विभाजित या यहां तक ​​कि सूचियां: विपरीत –

0

यदि आप अपनी सूची बनाते हैं ताकि यह टुपल्स से बना हो, तो आप lists:keyreplace का उपयोग कर सकते हैं।