3
$\begingroup$

Given two lists of equal length, l1 and l2, both consisting of sublists that are either empty or non-empty - but corresponding sublists are never non-empty - the task is to consolidate or "collapse" the lists to make a new list newList where

  • if the nth element of l1 is an empty list, but the same element of l2 is not, then newList[[n]] takes that sublist from l2;
  • if the nth element of l1 is non-empty, but the same element of l2 is an empty list, then newList[[n]] takes that sublist from l1;
  • if the nth element of both l1 and l2 are empty lists, then so will be the same element of newList

I have some working code for such a function, but I'm curious if there is a simpler or faster way to execute this sort of task. Perhaps I've overlooked a built-in method? Any suggestions appreciated (even for making the question title more concise).

Collapse[l1_List, l2_List] := Module[

    {newList, n, commonLength},

    newList = {};

    If[
        Length[l1] === Length[l2],

        commonLength = Length[l1]; n = 1;
        While[
            n <= commonLength,
            If[
                (l1[[n]] === {}) && (l2[[n]] =!= {}),
                AppendTo[newList, l2[[n]]],

                    If[
                        (l1[[n]] =!= {}) && (l2[[n]] === {}),
                        AppendTo[newList, l1[[n]]],

                        If[
                            (l1[[n]] =!= {}) && (l2[[n]] =!= {}),
                            Print["Lists are not collapsible"],
                            AppendTo[newList, {}]
                        ];

                    ];

                ];

            n++

        ];,

        Print["Lists are incompatible"];

    ];

    If[
        newList =!= {},
        Return[newList]
    ];

];

Test cases

Collapse[{{}}, {{}}]
(* {{}} *)

Collapse[{{}}, {{1}}]
(* {{1}} *)

Collapse[{{}, {1}, {}}, {{}, {}, {a}}]
(* {{}, {1}, {a}} *)

Collapse[{{}}, {{}, {}}]
(* Lists are incompatible *)

Collapse[{{1}}, {{a}}]
(* Lists are not collapsible *)
$\endgroup$
5
$\begingroup$

You can use Which to generalize If statements, along with Join and MapThread to get:

collapse[l1_, l2_] := Which[
  Length[l1] != Length[l2],
  Print["Lists are incompatible"],
  Max[Min /@ Map[Length, Transpose[{l1, l2}], {2}]] != 0,
  Print["Lists are not collapsible"],
  True,
  MapThread[Join, {l1, l2}]]

Test lists all work as desired.

$\endgroup$
5
$\begingroup$

I would create a helper function:

join[{}, a_] := a
join[a_, {}] := a
join[a_, b_] := (Print["Lists are not collapsible"]; $Failed)

collapse[a_, b_] := Quiet @ Check[
    MapThread[join, {a, b}],
    Print["Lists are incompatible"],
    MapThread::mptc
]

It's not exactly what your function returns, but it shouldn't be difficult to modify.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.