Quickly retrieve items from nested lists

This is the main question about manipulating lists in Mathematica. I have a large list where each element has the following schematic form: {List1, List2, Number}. For instance,

a = {{{1,2,3},{1,3,2},5},{{1,4,5},{1,0,2},10},{{4,5,3},{8,3,4},15}}} .

I want to create new lists in which there are only some parts from each sublist. For example, select the third item from each sublist to get {5,10,15} from the above. Or discard the third element to return {{{1,2,3}, {1,3,2}}, {{1,4,5}, {1,0,2}}, {{4,5, 3 }, {8,3,4}}}.

I can do this using the table command to create new lists, e.g.

 Table[a[[i]][[3]],{i,1,Length[a]} 

but I was wondering if there should be a faster way to work with large lists.

+6
source share
3 answers

In Mathematica version 5 and later, you can use the All keyword in various ways to indicate a crawl.

For example, instead of your table, you can write

 a[[All,3]] 

Here, Mathematica converts everything to all valid indices for the first dimension, then takes the third of the next dimension.

This is usually done more efficiently than creating a loop with the Mathematica programming language. This is really good for uniform lists, where the things you want to select or scan always exist.

Another effective notation and shortcut: ;; Syntax:

 a[[ All, 1 ;; 2]] 

scans the first level a and selects everything from the 1st to 2nd element of each sublist, just like your second case.

Virtually everything and ;; can be combined with any number of levels. ;; can even be used like any iterator in Mathematica:

 a[[ start;;end;;step ]] 

will perform the same actions as

 Table[ a[[i]], {i,start,end,step}] 

and you can omit one of the beginning, end or step, it is filled by default: 1, Length [(implicit list)] and 1.

Another thing you can find in math help: ReplacePart and MapAt , which allow programmatic replacement of structured expressions. The main thing to use this effectively is that in ReplacePart you can use patterns to indicate the coordinates of things that need to be replaced, and you can define functions to apply them.

Example with your data

 ReplacePart[a, {_, 3} -> 0] 

replaces every third part of each subscription 0.

 ReplacePart[a, {i : _, 3} :> 2*a[[i, 3]]] 

doubles every third part of each sublist.

+7
source

According to the authors, Part-based approaches need well-formed data, but Made to reliably separate lists:

Using your a,

 a = {{{1, 2, 3}, {1, 3, 2}, 5}, {{1, 4, 5}, {1, 0, 2}, 10}, {{4, 5, 3}, {8, 3, 4}, 15}}; Cases[a,{_List,_List,n_}:>n,Infinity] {5, 10, 15} 

Other fragments of the record may be extracted in similar forms.

A part-based approach will depend on malformed data, such as:

 badA = {{{1, 2, 3}, {1, 3, 2}, 5}, {{1, 4, 5}, {1, 0, 2}, 10}, {{4, 5, 3}, {8, 3, 4}, 15}, {baddata}, {{1, 2, 3}, 4}}; badA[[All,3]] {{{1, 2, 3}, {1, 3, 2}, 5}, {{1, 4, 5}, {1, 0, 2}, 10}, {{4, 5, 3}, {8, 3, 4}, 15}, {baddata}, {{1, 2, 3}, 4}}[[All, 3]] 

but Cases will pass garbage, working only according to relevant data

 Cases[badA, {_List, _List, s_} :> s, Infinity] {5, 10, 15} 

Hth,

Fred klinger

+2
source

You can use Part (the abbreviation [[...]]) for this:

 a[[All, 3]] a[[All, {1, 2}]] 
+1
source

All Articles