Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
6 years ago
Solved

List.Unzip wanted

let suppose we have two lists for which I want to keep the correspondence in the order of the elements.
So if I change the order of the first one of the lists, the elements of the second list also arrange themselves in corresponding positions.
This is easily done using the List.Zip function.

But to get back two separate lists  you need a sort of List.Unzip function.

I imagined one based on the use of List.accumulate


How else can you do the reverse operation of List.Zip?

  • Hi Anonymous 

     

    You can zip it again, this will reverse the zip, or am I missing something?

    = List.Zip( List.Zip( { { 1, 2 }, { 3, 4 }, { 5, 6 } } ) )

     

    Best Regards,
    Mariusz

    If this post helps, then please consider Accepting it as the solution.

    Please feel free to connect with me.
    LinkedIn

     

5 Replies

  • Mariusz's avatar
    Mariusz
    Community Champion

    Hi Anonymous 

     

    You can zip it again, this will reverse the zip, or am I missing something?

    = List.Zip( List.Zip( { { 1, 2 }, { 3, 4 }, { 5, 6 } } ) )

     

    Best Regards,
    Mariusz

    If this post helps, then please consider Accepting it as the solution.

    Please feel free to connect with me.
    LinkedIn

     

    • Anonymous's avatar
      Anonymous
      Not applicable

      wow. this is the solution :-).

       

      I was speculating on the InsertRanges

      insertRanges 

       

      function and I was thinking about situations of possible errors to manage.
      In particular, I was thinking of cases where the different length of the vectors involved can lead to error.
      Aside from these cases, a potential error situation occurred to me which also depends on the order of the elements in the vectors.
      And on this I looked for ways to manage the situation.

       

      la situazione si potrebbe presentare quando positions and ranges are, for instance,

      {1, 5, 2} and  {22,55, {33,44}}.

       

       

       

       

      I tryed to solve in the following way:

       

       

       

      let
          Source = List.Sort(List.Zip({{1, 5, 2}, {22,55, {33,44}}}),each _{0})
      in
          List.Accumulate(Source, {{},{}},(s,c)=>{s{0}&{c{0}},s{1}&{c{1}}})

       

       

      But now there is not needs of news unzip function.

      • Anonymous's avatar
        Anonymous
        Not applicable

        ...

        in some respects the transformation carried out by the list.zip function on a set of lists is analogous (isomorphic?!) to that made by the table.transpose function on the set of columns of a table.
        therefore like the transpose (transpose (T)) = T, should be also List.Zip (list.Zip (lists)) = lists

        this property indicates yet another way of realizing the list.zip function through other functions

         

         

         

         

        let
            ListZipUnZip = (lsts) =>  Table.ToColumns(Table.Transpose(Table.FromColumns(lsts)))
        in
            ListZipUnZip

         

         

         

        of course also the dual situation is valid.

        if you wanted, for very personal reasons, to simulate the Table.Transpose function, you could use List.Zip

         

         

        let
            transpose = (tab) =>  Table.FromColumns(List.Zip(Table.ToColumns(tab)))
        in
            transpose

         

         

  • Smauro's avatar
    Smauro
    Solution Sage

    Hey Anonymous ,

    I came up with this:

     

    (ListGiven as list) as list =>
        let
            n = List.Count(ListGiven{0}),
            Acc =
                (ListGiven, k, n) =>
                    let
                        ListK =
                            if k < n then
                                List.Transform(ListGiven, each _{k})
                            else
                                {},
                        NewList =
                            if k < n then
                                ListK & @Acc(ListGiven, k + 1, n)
                            else
                                ListK
                    in
                        NewList,
            UnZipped = Acc(ListGiven, 0, n)
        in
            UnZipped

     

    Mariusz' answer is better and certainly easier. What I came up with just gives one list.

     

  • Smauro's avatar
    Smauro
    Solution Sage

    Well,

     

    Now I've made a tweaked List.Zip:

     

    (ListGiven as list) as list =>
        let
            n =
                List.Max(
                    List.Transform(
                        ListGiven,
                        each try List.Count(_) otherwise 1
                    )
                ),
            GetK =
                (k) =>
                    List.RemoveFirstN(
                        List.RemoveLastN(
                            List.Transform(
                                ListGiven,
                                each try _{k} otherwise null
                            ),
                            each _ = null
                        ),
                        each _ = null
                    ),
            Zip =
                List.Generate(
                    () =>
                        [
                            l =
                                List.RemoveFirstN(
                                    List.RemoveLastN(
                                        List.Transform(
                                            ListGiven,
                                            each try _{0} otherwise _
                                        ),
                                        each _ = null
                                    ),
                                    each _ = null
                                ),
                            k = 1
                        ],
                    each [k] <= n,
                    each
                        [
                            l = GetK([k]),
                            k = [k] + 1
                        ],
                    each [l]
                )
        in
            Zip

     

    Contrary to List.Zip, it will also take single values, and cut leading and trailing nulls.

     

    If you want to test it, you could name it fnListZip and use this:

     

    let
        l = {1,3,5,7,9},
        k = {2,4,6},
        #"ListZip(l)" = List.Zip({l}),
        #"fnListZip(l)" = fnListZip({l}),
        #"ListZip(k,l)" = List.Zip({k,l}),
        #"fnListZip(k,l)" = fnListZip({k, l}),
        #"ListZip(ListZip(k,l))" = List.Zip(#"ListZip(k,l)"),
        #"fnListZip(fnListZip(k,l))" = fnListZip(#"fnListZip(k,l)"),
        #"ListZip(l,k,l)" = List.Zip({l, k, l}),
        #"fnListZip(l,k,l)" = fnListZip({l, k, l}),
        #"ListZip(ListZip(l,k,l))" = List.Zip(#"ListZip(l,k,l)"),
        #"fnListZip(fnListZip(l,k,l))" = fnListZip(#"fnListZip(l,k,l)"),
        NotReallyAListZip = {{1,2},{3,4},{5,6},7,9},
        #"ListZip(NotReallyAListZip)" = List.Zip(NotReallyAListZip),
        #"fnListZip(NotReallyAListZip)" = fnListZip(NotReallyAListZip),
        NotReallyAListZipB = {1,2,3,4,{5,"Here Is Something"},7,9},
        #"ListZip(NotReallyAListZipB)" = List.Zip(NotReallyAListZipB),
        #"fnListZip(NotReallyAListZipB)" = fnListZip(NotReallyAListZipB)
    in
        #"fnListZip(NotReallyAListZipB)"

     

     

    Best,

    Spyros