Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change an element in a list in erlang

I have a list which I have used the function lists:nth() on to return the value of an element at a certain index. Does anyone know how I can edit this value?

EDIT: Here is a bit more information.

Say I had a list L which represents a line of a text based grid

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

And I want to access a specified element say for example the third one and change it to E. Then if I was to use the list L again it would be

[H,H,E,H,H]

I hope this makes more sense.

Thank you.

like image 641
MulletDevil Avatar asked Jan 23 '11 19:01

MulletDevil


1 Answers

While using functions from lists may result in code that seems clearer it is less efficient as the list of elements before the element you want to change will be copied twice. It is more efficient to write the function yourself, and as you will probably wrap the code using lists in a function I don't feel it will be less clear.

Instead of the code by @D.Nibon I would write the function as:

%% 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.

The argument order can be discussed; unfortunately the lists module is no help here as it is inconsistent within the module. While this is not a tail-recursive function I feel that it is clearer. Also the difference in efficiency is small or non-existent so I would go with clarity. For more information about this issue see:

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

For a more versatile function instead of just the new value you could pass a fun which would be called with the old value and return the new value. In a library I would probably have both.

like image 69
rvirding Avatar answered Oct 26 '22 10:10

rvirding