# Select data from a structured list

Let's suppose we have the following structure of data

data = {{1}, {0.0109, -12.7758, -0.00980164, 0.00032368},
{1.0218, -12.7764, -0.00948724, 0.00064337},
{2.0327, -12.7772, -0.00905215, 0.00095516},
{2}, {0.0109, -12.7758, -0.00980164, 0.00032368},
{1.0218, -12.7764, -0.00948724, 0.00064337},
{2.0327, -12.7772, -0.00905215, 0.00095516},
{3}, {0.0109, -12.7758, -0.00980164, 0.00032368},
{1.0218, -12.7764, -0.00948724, 0.00064337},
{2.0327, -12.7772, -0.00905215, 0.00095516},
{4}, {0.0109, -12.7758, -0.00980164, 0.00032368},
{1.0218, -12.7764, -0.00948724, 0.00064337},
{2.0327, -12.7772, -0.00905215, 0.00095516},
{5}, {0.0109, -12.7758, -0.00980164, 0.00032368},
{1.0218, -12.7764, -0.00948724, 0.00064337},
{2.0327, -12.7772, -0.00905215, 0.00095516}}


Then, I want the following: I want to select those data for which the first number of the four is less than 2, keep the counting lone integers and keep only the last three columns of the sets. In other words, I want to produce the following new data

data2 = {{1}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{2}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{3}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{4}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{5}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337}}


Any suggestions?

Maybe there is something more elegant, but there you go:

Cases[data, {n_Integer} | {_?(LessThan[2]), b__} :> {n, b}]

• Cases[data, {n_Integer} | {_?(LessThan[2]), b__} :> {n, b}] a can be deleted :) Commented Jan 12, 2023 at 17:04
• @AsukaMinato Good point. Commented Jan 12, 2023 at 17:06
SequenceReplace[{ a : {_, _, _, _} ...} :>
Sequence @@ (Rest /@ Select[First@# <= 2 &]@{a})] @ data


{{1}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337},
{2}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337},
{3}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337},
{4}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337},
{5}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}}

A trivial way:

1. select those data for which the first number of the four is less than 2

2. keep the counting lone integers

3. keep only the last three columns of the sets.

translate:

f = Which[Length @ # === 1, Sow @ #;, (* 2 *)
#[[1]] < 2, Sow @ #[[-3;;]]; (* 1, 3 *)
]&;
data //
Map[f] //
Reap //
Last // First


{{1}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}, {2}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}, {3}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}, {4}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}, {5}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}}

res1 = data /. {{a_, b_, c_, d_} :> {b, c, d} /; a < 2 , {a_, b_, c_,
d_} :> Nothing}


Or phrased the other way round:

res2 = data /. {{a_, b_, c_, d_} :>
Nothing /; a > 2 , {a_, b_, c_, d_} :> {b, c, d}}


Or

res6 = Which[Length@# == 1, #,
Length@# == 4 && First@# < 2, Rest@#,
True, Nothing
] & /@ data


Or

res7 = Select[(PadLeft[#, 4, \[Wolf]] & /@ data),
First@# < 2 || First@# == \[Wolf] &][[All, 2 ;;]] /. \[Wolf] ->
Nothing


Result:

{{1}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}, {2}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}, {3}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}, {4}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}, {5}, {-12.7758, -0.00980164, 0.00032368}, {-12.7764, -0.00948724, 0.00064337}}

Using Table, If and Or:

Table[If[Length[data[[i]]] == 1, data[[i]], Or[If[Length[data[[i]]] == 4
&& First[data[[i]]] < 2, Rest@data[[i]], Nothing]]], {i, 1, Length[data]}]


Using Tableand Which:

Table[Which[Length[data[[i]]] == 1, data[[i]],
Length[data[[i]]] == 4 && First[data[[i]]] < 2, Rest@data[[i]],
Length[data[[i]]] == 4 && First[data[[i]]] > 2, Nothing], {i, 1,
Length[data]}]


Using Table and Piecewise:

Table[Piecewise[{{data[[i]], Length[data[[i]]] == 1},
{Rest@data[[i]],Length[data[[i]]] == 4 && First[data[[i]]] < 2}}, Nothing],
{i, 1, Length[data]}]


Result:

(*  {{1}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{2}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{3}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{4}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{5}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337}}*)


Don't forget the functional way (which might be more useful/readable when things get more complicated)

foo[x : {_}] := x
foo[{x_, b__}] := {b} /; x < 2
foo[_] := Nothing


Then

Map[foo,data]// Column

{1}
{-12.7758,-0.00980164,0.00032368}
{-12.7764,-0.00948724,0.00064337}
{2}
{-12.7758,-0.00980164,0.00032368}
{-12.7764,-0.00948724,0.00064337}
{3}
{-12.7758,-0.00980164,0.00032368}
{-12.7764,-0.00948724,0.00064337}
{4}
{-12.7758,-0.00980164,0.00032368}
{-12.7764,-0.00948724,0.00064337}
{5}
{-12.7758,-0.00980164,0.00032368}
{-12.7764,-0.00948724,0.00064337}


Using ReplaceAll

ReplaceAll[{{a_ /; a < 2, b__} :> {b}, {_, _, _, _} :> Nothing}] @ data


returns

(*  {{1}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{2}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{3}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{4}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337},
{5}, {-12.7758, -0.00980164, 0.00032368},
{-12.7764, -0.00948724, 0.00064337}} *)


You can use a combination of list comprehension and slicing to achieve your desired outcome. Here's one way you could write the code to produce the data2 list:

data2 = [[i] + [sublist[1:4] for sublist in data if sublist[0] < 2 and sublist[0] == int(sublist[0])] for i in range(1,6)] This code uses nested list comprehension to iterate over the data list. The outer list comprehension iterates over the range 1 to 5, which corresponds to the counting integers you want to keep. The inner list comprehension iterates over the sublists in the data list, and filters out the sublists that do not meet the conditions specified in your question (the first element is less than 2, and the first element is an integer). The slice sublist[1:4] is used to select the last three columns of the sets.

• Please sure the actual code used and the result obtained. Commented Jan 13, 2023 at 14:49