Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

two list operations in mathematica

I have two list operations which I would like to ask for help. The way I implemented them is not very elegant, so I want to learn from you experts.

1) Suppose I have two lists, one is like {{0,2,4},{1,3,2},{2,0,4}} and the other is {{1,3,7},{2,4,6},{3,1,9}}. I want to either based on the value, or based on some criterion to filter through the first list, and then get the corresponding elements in the second. For example, based on value which is non-zero, I want to get {{3,7},{2,4,6},{3,9}}. Based on the condition greater than 2, I want to get {{7},{4},{9}}.

2) I have a list such as {{{1,2},{1,1}},{{1,3},{2,4}},{{1,2},{2,3}},{{1,4},{3,3}}}. I want to form {{{1,2},{{1,1},{2,3}}},{{1,3},{{2,4}}},{{1,4},{{3,3}}}. That is, I want to group those second lists if the first element is the same. How can I do this in a beautiful way?

Many thanks.

like image 200
Qiang Li Avatar asked Dec 09 '22 10:12

Qiang Li


2 Answers

For the first part, you want Pick:

In[27]:= Pick[{{1,3,7},{2,4,6},{3,1,9}},{{0,2,4},{1,3,2},{2,0,4}},_?Positive]
Out[27]= {{3,7},{2,4,6},{3,9}}

In[28]:= Pick[{{1,3,7},{2,4,6},{3,1,9}},{{0,2,4},{1,3,2},{2,0,4}},_?(#>2&)]
Out[28]= {{7},{4},{9}}

For the second question, GatherBy gets you most of the way there:

In[29]:= x = GatherBy[{{{1, 2}, {1, 1}}, {{1, 3}, {2, 4}}, {{1, 2}, 
    {2, 3}}, {{1, 4}, {3, 3}}}, First]

Out[29]= {{{{1, 2}, {1, 1}}, {{1, 2}, {2, 3}}}, {{{1, 3}, 
    {2, 4}}}, {{{1, 4}, {3, 3}}}}

And then you can apply a rule to clean things up a bit:

In[30]:= x /. l:{{a_, _}..} :> {a, Last /@ l}

Out[30]= {{{1, 2}, {{1, 1}, {2, 3}}}, {{1, 3}, {{2, 4}}},
    {{1, 4}, {{3, 3}}}}
like image 85
Michael Pilat Avatar answered Dec 11 '22 22:12

Michael Pilat


As Michael said, Pick is definitely the way to go for the first one.

For the second part, I'd like to offer an alternative that lets you do this in one line: SelectEquivalents. (I know, rather self promoting, but I use this function a lot.) To get the result your looking for, simply enter

In[1] := SelectEquivalents[ <list>, First, Last, {#1,#2}& ]
Out[1]:= {{{1, 2}, {{1, 1}, {2, 3}}}, {{1, 3}, {{2, 4}}}, {{1, 4}, {{3, 3}}}}

Internally, SelectEquivalents uses Reap and Sow, so First tags each element in <list>, Last transforms the element into the form we wish to use, and {#1, #2}& returns a list with elements of the form {Tag, {<items with that tag>}}. The advantage is that you get to specify everything in one step getting you what you want without subsequent transformations.

like image 30
rcollyer Avatar answered Dec 11 '22 23:12

rcollyer