| Author |
Message |
< Erlang ~ Make operation to first element in each sublist |
| niglas |
Posted: Wed Feb 02, 2011 12:44 pm |
|
|
|
User
Joined: 31 Jan 2011
Posts: 12
|
I would like to add an "s" to the first element in each sublist in a multidimensional list.
Like this...
From:
Code: [["elephant","walk"],
["crocodile","bite"],
["star","twinkle"]]
To:
Code: [["elephants","walk"],
["crocodiles","bite"],
["stars","twinkle"]] |
|
|
| Back to top |
|
| rvirding |
Posted: Wed Feb 02, 2011 1:06 pm |
|
|
|
User
Joined: 30 Aug 2006
Posts: 452
Location: Stockholm, Sweden
|
Three different styles for doing it:
Defining a function to do it:
Code:
apps([[H|T]|Rest]) ->
[[H ++ "s"|T]|apps(Rest)];
apps([]) -> [].
Using lists:map:
Code:
lists:map(fun ([H|T]) -> [H ++ "s"|T] end, MultiList)
Using list comprehensions:
Code:
AppS = fun([H|T]) -> [H ++ "s"|T] end,
[ AppS(E) || E <- MultiList ]
Using a fun to generate elements for the output list makes the comprehension a bit easier to read.
They are all equivalent, which one you choose is a matter of style. |
_________________ Robert Virding, Erlang Solutions Ltd. |
|
| Back to top |
|
| niglas |
Posted: Wed Feb 02, 2011 1:59 pm |
|
|
|
User
Joined: 31 Jan 2011
Posts: 12
|
Thanks a lot!
What if I want to swap the elements too?
Like this: Code: [["walk","elephants"],
["bite","crocodiles"],
["twinkle","stars"]]
Tried...Code: lists:map(fun ([H|T]) -> [T|H ++ "s"] end, MultiList) ...but it didn't quite work out the way I expected (some numbers were added). |
|
|
| Back to top |
|
| zajda |
Posted: Thu Feb 03, 2011 10:16 am |
|
|
|
User
Joined: 22 Aug 2009
Posts: 83
|
T holds a list since it is tail
List = [HeadElement | TaiList]
| is a list constructor which adds element as a new head of a list.
So, to swap elements either reverse whole list
Code: lists:map(fun ([H|T]) -> lists:reverse([H ++ "s"|T]) end, MultiList)
or extract the second element from a list:
Code: lists:map(fun ([E1,E2]) -> [E2|[E1]] end, MultiList)
the same as:
Code: lists:map(fun ([E1,E2]) -> [E2] ++ [E1] end, MultiList)
(above funs match only on 2 element lists - those with coma, where the one with pipe matches on any number of elements)
Using pipe instead of ++ is considered to be much cooler (used to be faster). |
|
|
| Back to top |
|
| rvirding |
Posted: Sat Feb 05, 2011 5:30 pm |
|
|
|
User
Joined: 30 Aug 2006
Posts: 452
Location: Stockholm, Sweden
|
Sort of. @zajda's 1st version works for a list of any length if you want to append "s" to the first element and reverse the whole list. It will not move the first element to the end of the list. A version which does this on any length list is:
Code: appsl(List) ->
lists:map(fun ([H|T]) -> T ++ [H ++ "s"] end, List).
There is no getting around the appends (++) here.
Now [E1|[E2]] and [E1,E2] are exactly equivalent, the second being syntactic sugar for the first. The compiler tries to optimise expressions with ++ as much as possible. When the first argument is a literal list it can remove the ++ completely by the following transformation:
[A,B,C] ++ Rest --> [A,B,C|Rest]
The same is done when ++ occurs in a pattern which is why the only time ++ can occur in a pattern is when the first argument is a literal list. This means that @zajda's last two version are in fact equivalent.
Sorry for being a bit didactic here. |
_________________ Robert Virding, Erlang Solutions Ltd. |
|
| Back to top |
|
|
|