我有一个列表,我使用了函数列表:nth()on来返回某个索引处元素的值。有谁知道我怎么能编辑这个值?
任何帮助都会很棒
感谢
标记。
编辑:这里有更多信息。 假设我有一个列表L,它代表一行基于文本的网格
L = [H,H,H,H,H].
我想访问一个指定的元素,例如第三个,然后将其更改为E.然后,如果我再次使用列表L,那将是
[H,H,E,H,H]
我希望这更有意义。
谢谢。
答案 0 :(得分:18)
列表是不可变的,因此您无法“更改”列表中的项目。如果你真的想要替换给定位置的项目,你应该在具有(更改的)元素和剩余列表的元素之前附加列表:
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]
编辑:情况有点不寻常,但是......你手头有特定的问题吗?也许它可以用例如表达更好列表:地图?
答案 1 :(得分:11)
虽然使用lists
中的函数可能会导致代码看起来更清晰但效率较低,因为元素列表之前要更改的元素将被复制两次。自己编写函数效率更高,因为您可能会在函数中使用lists
包装代码,但我觉得它不太清楚。
而不是@ D.Nibon的代码,我会将函数编写为:
%% 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
,它将使用旧值调用并返回新值。在图书馆,我可能会同时拥有这两个。
答案 2 :(得分:3)
使用列表时,所有元素通常具有相似的数据类型或含义。您很少看到["John Doe","1970-01-01","London"]
之类的列表,而是#person{name="John Doe",...}
或甚至{“John Doe”,...}等列表。要更改记录和元组中的值:
-record(person,{name,born,city}).
f(#person{}=P) -> P#person{city="New City"}. % record
f({_,_,_,}=Tuple) -> erlang:setelement(3,Tuple,"New City"). % tuple
这可能无法解决您的特定问题。在评论中采用自己的例子:
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。
答案 3 :(得分:3)
L = [H,H,H,H,H].
我想访问一个指定的元素,例如第三个,然后将其更改为E.然后,如果我再次使用列表L,那将是
[H,H,E,H,H]
成为一个真正的挑剔者。在Erlang中,数据是持久性和不可变。定义L = ...
部分后,L
就会一成不变。你无法从那里改变它。您可以做的是创建一个新值并将其绑定到另一个变量,L1
然后停止使用L
。然后,垃圾收集器将快速完成L
的简短工作并回收它使用的内存。
因此,再次使用L
更改其内容有点不对,因为这是不可能的。
值得一提的另一点是,如果您将列表视为数组,那么您可以使用数组(来自array
模块)或使用dict(来自dict
模块)。它极大地提高了您的查找和更新速度。如果您最常做的是遍历列表以处理所有元素,那么列表可能会成为赢家。
答案 4 :(得分:0)
如果您构建列表以使其由元组组成,则可以使用lists:keyreplace。
答案 5 :(得分:0)
from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.uix.image import AsyncImage
from kivy.properties import StringProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
LINK_HOLDER = ''
class WindowManager(ScreenManager):
pass
class First(Screen):
pass
class Second(Screen):
rv_data = [{'text': 'random text here','source': LINK_HOLDER}] # being assigned at run time ???
'''
links to use:
https://www.dropbox.com/s/cku7lcyyikupyda/ruby.png?raw=1
https://www.dropbox.com/s/nfkkt1b90p2g5qh/python.jpeg?raw=1
https://www.dropbox.com/s/5840br37wwvymtr/julia.png?raw=1
'''
class ImageAndTitle(BoxLayout):
title = StringProperty()
source = StringProperty()
class ExampleApp(App):
def build(self):
return load
load = Builder.load_string('''
WindowManager:
First:
Second:
<First>:
name: 'first'
FloatLayout:
Button:
text: 'Python'
pos: 100, 300
size_hint: None, None
size: 100, 100
on_press:
global LINK_HOLDER
LINK_HOLDER = 'https://www.dropbox.com/s/cku7lcyyikupyda/ruby.png?raw=1'
app.root.current = 'second'
root.manager.transition.direction = 'right'
Button:
text: 'Ruby'
pos: 250, 300
size_hint: None, None
size: 100, 100
on_press:
global LINK_HOLDER
LINK_HOLDER = 'https://www.dropbox.com/s/nfkkt1b90p2g5qh/python.jpeg?raw=1'
app.root.current = 'second'
root.manager.transition.direction = 'right'
Button:
text: 'Julia'
pos: 450, 300
size_hint: None, None
size: 100, 100
on_press:
global LINK_HOLDER
LINK_HOLDER = 'https://www.dropbox.com/s/5840br37wwvymtr/julia.png?raw=1'
app.root.current = 'second'
root.manager.transition.direction = 'right'
<ImageAndTitle>:
Label:
text: root.title
AsyncImage:
source: root.source
<Second>:
name: 'second'
GridLayout:
cols: 2
rows: 1
BoxLayout:
orientation: 'vertical'
RecycleView:
viewclass: 'ImageAndTitle'
data: root.rv_data
RecycleBoxLayout:
default_size_hint: 1, None
default_size: 100, 30
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
BoxLayout:
orientation: 'vertical'
Label:
text: 'five'
Label:
text: 'six'
''')
if __name__ == '__main__':
ExampleApp().run()
答案 6 :(得分:-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]
不漂亮,但我打赌效率很高。