Erlang/OTP Forums

Author Message

<  Erlang  ~  Make operation to first element in each sublist

niglas
Posted: Wed Feb 02, 2011 12:44 pm Reply with quote
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"]]
View user's profile Send private message
rvirding
Posted: Wed Feb 02, 2011 1:06 pm Reply with quote
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.
View user's profile Send private message Visit poster's website MSN Messenger
niglas
Posted: Wed Feb 02, 2011 1:59 pm Reply with quote
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).
View user's profile Send private message
zajda
Posted: Thu Feb 03, 2011 10:16 am Reply with quote
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 Wink (used to be faster).
View user's profile Send private message
rvirding
Posted: Sat Feb 05, 2011 5:30 pm Reply with quote
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.
View user's profile Send private message Visit poster's website MSN Messenger

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum