Message Boards Message Boards

1
|
14392 Views
|
15 Replies
|
11 Total Likes
View groups...
Share
Share this post:

Flattening a list by preserving the innermost level

Is there a better way to compute the following?
In[1]:= list = {{1, 2}, {{3, 4}, {5, 6}, {7, 8}, {9, 10}}, {{11, 12}}};
        Partition[Flatten[list], 2]
Out[2]= {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}
POSTED BY: Matthias Odisio
15 Replies
Posted 3 years ago

Raymond, does the following give what you want?

l = {{a, {a, a}}, {b, {b, {b}}}, {c, {c, {c, {c, c}}}}};

Flatten[Map[Flatten[#, Depth[#] - 3] &, l], 1]
(* {a, {a, a}, b, b, {b}, c, c, c, {c, c}} *)
POSTED BY: Hans Milton
Posted 3 years ago

Thank you again Rohit -- but

I don't think Mathematica likes me. Try as I may, I fail ---

l = {{a, {a, a}}, {b, {b, {b}}}, {c, {c, {c, {c, c}}}}};
l // Flatten
l // Map[Flatten]
Map[Flatten, l, {4}]
Map[Flatten[l], {4}]
Map[Flatten, l]
Map[Flatten, l, 2]

enter image description here

I can only get Map to Flatten elements at level 1 and no further. I am afraid to ask, what am I am doing wrong this time.

POSTED BY: Raymond Low
Posted 3 years ago

The problem is that Flatten expects a List. At some levels there is no List, just a single value. Hence the error message "Flatten::normal: Nonatomic expression expected at position 1 in Flatten[a]."

What is the final result you want for the list?

l = {{a, {a, a}}, {b, {b, {b}}}, {c, {c, {c, {c, c}}}}};
POSTED BY: Rohit Namjoshi
Posted 3 years ago

Please post code that can be copied / pasted, not images.

// generally is used with one argument, but Map requires two arguments, so the first argument is wrapped

This is called an operator form and is documented.

Map applies the function only to level 1 elements

Map can be applied to whatever level(s) you want using the three argument form. Check the documentation.

l = {{a, {a, a}}, {b, {b, {b}}}, {c, {c, {c, {c, c}}}}}

ClearAll@f
(* Levels 1 to 3 *)
Map[f, l, 3]
(* {f[{f[a], f[{f[a], f[a]}]}], f[{f[b], f[{f[b], f[{b}]}]}], f[{f[c], f[{f[c], f[{c, {c, c}}]}]}]} *)

(* Level 4 only *)
Map[f, l, {4}]
(* {{a, {a, a}}, {b, {b, {f[b]}}}, {c, {c, {f[c], f[{c, c}]}}}} *)
POSTED BY: Rohit Namjoshi
Posted 3 years ago

Very good, Thank you Rohit.

// generally is used with one argument, but Map requires two arguments, so the first argument is wrapped

enter image description here enter image description here

Flatten removes all other levels...

Map applies the function only to level 1 elements, so each level 1 element is flattened to one level

enter image description here

POSTED BY: Raymond Low
Posted 3 years ago

Hi Rohi Thank you so much, True, and only as you have written it. If I use 'list' as an argument of Flatten, it ignores Map. Flatten[list] is the same as list //Flatten, but //Map[Flatten] is a different animal, how do I understand it?? What is it doing??

enter image description here

POSTED BY: Raymond Low
Posted 3 years ago

The signature of Map is Map[f, expr], not Map[f[expr]]. You want

Map[Flatten, list]
POSTED BY: Rohit Namjoshi
Posted 3 years ago

Hey Raymond,

Here is one way

list // Map[Flatten] // DeleteCases[{}]
POSTED BY: Rohit Namjoshi
Posted 3 years ago

How would I flatten the second level, but keep the first???

list = {{{}, {Quantity[20.18000030517578, "USDollars"]}, {Quantity[
      119.62999725341797`, "USDollars"]}, {Quantity[
      1.2599999904632568`, "USDollars"]}, {Quantity[
      15.390000343322754`, "USDollars"]}}, {{}, {Quantity[
      19.459999084472656`, "USDollars"]}, {Quantity[
      116.41000366210938`, "USDollars"]}, {Quantity[1.059999942779541,
       "USDollars"]}, {Quantity[12.670000076293945`, 
      "USDollars"]}}, {{}, {Quantity[18.110000610351562`, 
      "USDollars"]}, {Quantity[53.20000076293945, 
      "USDollars"]}, {Quantity[0.949999988079071, 
      "USDollars"]}, {Quantity[7.949999809265137, 
      "USDollars"]}}, {{}, {}, {}, {}, {}}};

enter image description here

Not this but close, I want to keep the three lists of four elements -- but the real application would have varying numbers of lists with varying numbers of elements

In[701]:= Flatten[list]

Out[701]= {Quantity[20.18000030517578, "USDollars"], 
 Quantity[119.62999725341797`, "USDollars"], 
 Quantity[1.2599999904632568`, "USDollars"], 
 Quantity[15.390000343322754`, "USDollars"], 
 Quantity[19.459999084472656`, "USDollars"], 
 Quantity[116.41000366210938`, "USDollars"], 
 Quantity[1.059999942779541, "USDollars"], 
 Quantity[12.670000076293945`, "USDollars"], 
 Quantity[18.110000610351562`, "USDollars"], 
 Quantity[53.20000076293945, "USDollars"], 
 Quantity[0.949999988079071, "USDollars"], 
 Quantity[7.949999809265137, "USDollars"]}
POSTED BY: Raymond Low
Posted 12 years ago
Maybe
In[205]:= Level[list, {-2}]
Out[205]= {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}
POSTED BY: Suba Thomas
Possibly
In[104]:= Cases[list, {__Integer}, Infinity]
Out[104]= {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}
POSTED BY: Oleksandr Pavlyk
To clarify, by "better" do you mean "faster (with large ragged arrays of machine integers that are packed when possible)"?

Or something different?
POSTED BY: Andrew Moylan
For my very problem, speed is not an issue. I was hoping to discover
an elegant alternative way, perhaps using an arcane (for me)
syntactic form of Flatten, Replace, or other related functions.

Paritosh's solution expresses well that I would like to "flatten" as
much as possible starting from the the outermost braces and stopping
so the innermost List is untouched.
POSTED BY: Matthias Odisio
How about
In[2]:= list /. List[List[x__]] -> List[x]
Out[2]= {{1, 2}, {{3, 4}, {5, 6}, {7, 8}, {9, 10}}, {11, 12}}
POSTED BY: Paritosh Mokhasi
Hello Matthias,
I believe your method is more efficient than this alternative:
Cases[list, {_Integer, _Integer}, Infinity]
Which is a different way of thinking about it.
Craig
POSTED BY: W. Craig Carter
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract