8
$\begingroup$

Given two lists of unequal length:

ind = Range[0, 4];

color = {"red", "green", "blue", "black"};

how can I produce efficiently the following list which is as long as the shorter of the two?

{{"red", 0}, {"green", 1}, {"blue", 2}, {"black", 3}}
$\endgroup$
  • 1
    $\begingroup$ Use Transpose. $\endgroup$ – C. E. Mar 5 '17 at 0:11
  • 2
    $\begingroup$ @C.E. Thanks for the comment but the lists do not have the same length. $\endgroup$ – Dimitris Mar 5 '17 at 0:14
  • $\begingroup$ ok, I missed that. Then you have to shorten the first list to match the length of the second list. You could for example use Transpose[{color, Take[ind, Length[color]]}. $\endgroup$ – C. E. Mar 5 '17 at 0:24
  • $\begingroup$ @C.E. Thanks again. I was wondering if there is a built-in function that "understands" that the two lists have different lengths and combines them in the proper manner, like zip function in Python. $\endgroup$ – Dimitris Mar 5 '17 at 0:30
  • 3
    $\begingroup$ To closers: I think this is a legitimate question given that the lists are of unequal length. $\endgroup$ – WReach Mar 5 '17 at 3:38
10
$\begingroup$

Some ideas:

Partition[Riffle[color, ind, {2, -1, 2}], 2]

Flatten[{color, ind}, {2}] // Cases[{_, _}]

{color, PadRight[ind, Length@color]}\[Transpose]

ind ~Riffle~ color ~Partition~ 2 ~Reverse~ 2

MapIndexed[{#, Extract[ind, #2]} &, color]

Take[#, All, Min[Length /@ #]]\[Transpose] &[{color, ind}]

All produce:

{{"red", 0}, {"green", 1}, {"blue", 2}, {"black", 3}}

I'll note that the last method, which was perhaps my most serious attempt to answer this pragmatically, can be applied to any number of lists:

fn = Take[#, All, Min[Length /@ #]]\[Transpose] &;

fn[{{1, 2, 3}, Alphabet[], 2^Range@5}]
{{1, "a", 2}, {2, "b", 4}, {3, "c", 8}}
$\endgroup$
  • $\begingroup$ You have once again lived up to your username. $\endgroup$ – Michael Seifert Mar 5 '17 at 20:59
5
$\begingroup$

Here is a function to do it for any two lists. It doesn't care about the order in which the lists appear as arguments.

makePairs[a_List, b_List] :=
  Transpose[Take[#, Min[{Length @ a, Length @ b}]] & /@ {a, b}]

makePairs[color, ind]

{{"red", 0}, {"green", 1}, {"blue", 2}, {"black", 3}}

makePairs[ind, color]

{{"red", 0}, {"green", 1}, {"blue", 2}, {"black", 3}}

$\endgroup$
  • $\begingroup$ FWIW that's pretty similar to my last method: Take[#, All, Min[Length /@ #]]\[Transpose] & $\endgroup$ – Mr.Wizard Mar 5 '17 at 6:23
  • 1
    $\begingroup$ @Mr.Wizard. The methods might be similar, but the programming philosophy illustrated by the two answer differ enough that I think this deserves to stand. $\endgroup$ – m_goldberg Mar 5 '17 at 6:25
  • $\begingroup$ You mean you're not a fan of the shotgun answer? :^) $\endgroup$ – Mr.Wizard Mar 5 '17 at 6:27
  • $\begingroup$ @Mr.Wizard. I like shotgun answers. I also think there should be room for other kinds. $\endgroup$ – m_goldberg Mar 5 '17 at 6:35
  • $\begingroup$ No argument from me on that point! $\endgroup$ – Mr.Wizard Mar 5 '17 at 6:55
4
$\begingroup$

Another variant:

DeleteCases[
 Transpose[PadRight[{color, ind}, Automatic, Missing]], {___, 
  Missing, ___}]
$\endgroup$
2
$\begingroup$
Block[{i = 1}, {#, ind[[i++]]} & /@ color]

{{"red", 0}, {"green", 1}, {"blue", 2}, {"black", 3}}

$\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.