SML - Unzip tuples in one list

598 views Asked by At

I need to "unzip" a list of tuples and even though I tried with the unzip function it doesn't do what I want to. In fact, as I understood the unzip function returns you a tuple of list, but what i want is this.

Giving a list of tuple like this:

L1 = [(("s0","l0"),("l0","s1")),(("s1","l1"),("l1","s2"))]

of type:

(string*string)*(string*string) list

the function should return me a single list composed by the unzipped tuples:

L2 = [("s0","l0"),("l0","s1"),("s1","l1"),("l1","s2")]

of type:

(string*string) list

The only solution I found is:

fun f(h as (x,y,z),nil) =  [(x,x^y^z)]@[(x^y^z,z)]
|f (h as (x,y,z),t::rest) = 
    let val i = ref 0
        in if !i=0 then (i := !i+1; (x,x^y^z)::f(h,t::rest)) else (i := !i-1;(x^y^z,z)::f(t,rest)) end;

and I thought it could work but when I run the function the system crashes.

1

There are 1 answers

0
Inaimathi On BEST ANSWER

I'm not entirely sure what the function you posted does, but it almost certainly won't unzip a list of 2-tuples for you. It seems to expect 3-tuples, and does some de-referencing/concatenation to boot. How did you find it?

If you want a function that takes a list of 2-tuples and returns a list of their elements, you can do

fun peel lst =
    let fun recur [] acc = List.rev acc
      | recur ((a, b)::rest) acc = 
        recur rest (b::a::acc)
    in 
    recur lst []
    end

that is, go through the list, collecting both elements of each tuple, and return the reverse of your accumulator when you get to the end.

Standard ML of New Jersey v110.76 [built: Thu Feb 19 00:37:13 2015]
- fun peel lst =
    let fun recur [] acc = List.rev acc
      | recur ((a, b)::rest) acc = 
        recur rest (b::a::acc)
    in 
    recur lst []
    end ;;
= = = = = = [autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val peel = fn : ('a * 'a) list -> 'a list
- peel [(("s0","l0"),("l0","s1")),(("s1","l1"),("l1","s2"))] ;;
val it = [("s0","l0"),("l0","s1"),("s1","l1"),("l1","s2")]
  : (string * string) list
- 

Because of the way its defined, it has the (possibly unnecessary bonus) that it can similarly process any list of 2-tuples.

- peel (peel [(("s0","l0"),("l0","s1")),(("s1","l1"),("l1","s2"))]) ;;
val it = ["s0","l0","l0","s1","s1","l1","l1","s2"] : string list
-