# Selecting sublists of different length if at least one element of the sublist fulfills a criterion

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.

• Related: (916), (8650). Possibly useful: (9719) Mar 19, 2015 at 8:57

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 & /@ #) &)]


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


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.

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

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

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