11
$\begingroup$

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?

$\endgroup$
0

8 Answers 8

16
$\begingroup$

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

Cases[data, {n_Integer} | {_?(LessThan[2]), b__} :> {n, b}]
$\endgroup$
2
  • 1
    $\begingroup$ Cases[data, {n_Integer} | {_?(LessThan[2]), b__} :> {n, b}] a can be deleted :) $\endgroup$ Commented Jan 12, 2023 at 17:04
  • $\begingroup$ @AsukaMinato Good point. $\endgroup$ Commented Jan 12, 2023 at 17:06
14
$\begingroup$
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}}

$\endgroup$
8
$\begingroup$

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}}

$\endgroup$
0
8
$\begingroup$
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}}

$\endgroup$
7
$\begingroup$

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}}*)
$\endgroup$
7
$\begingroup$

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}
$\endgroup$
1
$\begingroup$

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}} *)
$\endgroup$
0
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ Please sure the actual code used and the result obtained. $\endgroup$
    – bbgodfrey
    Commented Jan 13, 2023 at 14:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.