5

I have the following list, containing sublists with 1,2 or 3 elements.

 list= {{10.7}, {10.5}, {9.83},{7.64}, {4.76}, {4.21, 
      5.64}, {3.75}, {3.4, 5.11}, {3.13, 4.76, 6.5},{7, 5, 3}}

I have to select sublists if at least one element of the sublist is between 5 and 8. I think it should work with Select[], but I can't figure it out, because the sublists have different lengths.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
Niki
  • 960
  • 4
  • 14

6 Answers6

7

In Mathematica 10 you can use AnyTrue for this:

 list ~Select~ AnyTrue[5 <= # <= 8 &]
{{7.64}, {4.21, 5.64}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}}

You can also use VectorQ and Not:

Select[list, ! VectorQ[#, 5 > # || # > 8 &] &]
{{7.64}, {4.21, 5.64}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}}

If aiming for speed consider purely numeric operations. Assuming all positive numbers as in your example you could use:

Pick[list, UnitStep[Max /@ Clip[list, {5, 8}, {-1, -1}]], 1]
{{7.64}, {4.21, 5.64}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}}

Timings:

list = RandomReal[{0, 200}, {50000, 50}];

Select[list, AnyTrue[5 <= # <= 8 &]]                         // Timing // First
Select[list, ! VectorQ[#, 5 > # || # > 8 &] &]               // Timing // First
Pick[list, UnitStep[Max /@ Clip[list, {5, 8}, {-1, -1}]], 1] // Timing // First
0.8736

1.5288

0.0156

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
4

Some variations along with timings:

list = {{10.7}, {10.5}, {9.83}, {7.64}, {4.76}, {4.21, 
   5.64}, {3.75}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}};

The result for the list in the OP is the same for the different variations.

{{7.64}, {4.21, 5.64}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}}


TIMINGS

list = RandomReal[{0, 200}, {50000, 50}]; (* Mr. Wizard's test list *)

Using Between:

Select[AnyTrue[Between[{5, 8}]]][list] // Timing // First

3.40082

Using IntervalMemberQ:

Pick[list, 
 IntervalMemberQ[Interval[{5, 8}], #] & /@ list // Map[Apply[Or]]
 ] // Timing // First

1.49761

Using MemberQ with Pick:

Pick[list, MemberQ[#, _?(5 <= # <= 8 &)] & /@ list] // Timing // First

1.34161

Using MemberQ with Select:

Select[list, MemberQ[#, _?(5 <= # <= 8 &)] &] // Timing // First

1.29481


Mr. Wizards's last solution outperforms others by a factor of 80+ whenever sublists must be selected for containing any element within a continuous interval.

Syed
  • 52,495
  • 4
  • 30
  • 85
4
list = {{10.7}, {10.5}, {9.83}, {7.64}, {4.76}, {4.21, 5.64}, {3.75},
        {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}};
Select[list, Or @@ (5 <= # <= 8 & /@ #) &]
(* {{7.64}, {4.21, 5.64}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}} *)

You get the same result using siblings of Select:

Pick[list, Or @@ (5 <= # <= 8 & /@ #) & /@ list]
Cases[list, _?(Or @@ (5 <= # <= 8 & /@ #) &)]
kglr
  • 394,356
  • 18
  • 477
  • 896
2
list =
  {{10.7}, {10.5}, {9.83}, {7.64}, {4.76}, {4.21, 5.64}, 
  {3.75}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}};

f[a_][b_] /; Or @@ Map[Between[#, a] &] @ b := b
f[_][_] := Nothing

f[{5, 8}] /@ list

{{7.64}, {4.21, 5.64}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}}

f[{7, 8}] /@ list

{{7.64}, {7, 5, 3}}

eldo
  • 67,911
  • 5
  • 60
  • 168
2

Using another variant of Cases works, too:

Cases[list, {a___, x_, b___} /; 4 < x <= 5 -> {a, x, b}]
(* {{4.76}, {4.21, 5.64}, {3.13, 4.76, 6.5}, {7, 5, 3}} *)
Jinxed
  • 3,753
  • 10
  • 24
1

Using Extract and Position:

list = {{10.7}, {10.5}, {9.83}, {7.64}, {4.76}, {4.21, 5.64},
        {3.75}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}};

Extract[#, Position[#, {a___, x_, b___} /; 5 <= x <= 8]] &@list

({{7.64}, {4.21, 5.64}, {3.4, 5.11}, {3.13, 4.76, 6.5}, {7, 5, 3}})

E. Chan-López
  • 23,117
  • 3
  • 21
  • 44