Gathering a List efficiently

SeedRandom[123]
L = Table[RandomChoice[{1, 4} -> {{}, RandomChoice[CharacterRange["A", "G"], 
      RandomChoice[{2, 4, 6, 8}]]}], {15}]

{{"G", "E", "F", "C"}, {"G", "D", "B", "C", "D", "A"}, {"D", "B", "E", "E", "F", "D", "G", "G"}, {}, {"C", "C", "F", "A", "D", "C"}, {"B", "A", "G", "B"}, {"A", "E"}, {}, {}, {"C", "F"}, {"F", "E", "C", "E"}, {"G", "E"}, {"C", "E", "C", "A", "B", "A"}, {"G", "F", "G", "F", "D", "B", "A", "B"}, {"A", "C", "B", "E"}}

Q = Length;
{L0, L2, L4, L6, L8} = Pick[Range @ Length @ L, #- Q /@ L, 0] & /@ {0, 2, 4, 6, 8}

{{4, 8, 9}, {7, 10, 12}, {1, 6, 11, 15}, {2, 5, 13}, {3, 14}}

Or, as suggested by Kuba in comments:

{L0, L2, L4, L6, L8} = PositionIndex[Q /@ L] /@ {0, 2, 4, 6, 8} /. _Missing-> {}

same output


Pulling my approach out from the comments:

lists = {{1, 2}, {3, 4, 5, 6}, {7, 8, 9, 10}, {11, 12}};
func = Length;
values = {0, 2, 4, 6, 8};
Lookup[PositionIndex[func /@ lists], values, {}]
{{}, {1, 4}, {2, 3}, {}, {}}

I thought kglr's approach would be pretty fast (as Pick often is), but since we're dealing with unpacked arrays, it took a lot of special effort to get the most out of it. Here's a performance comparison.

SeedRandom[123]
lists = Table[
   RandomChoice[{1, 4} -> {{}, 
      RandomChoice[CharacterRange["A", "G"], 
       RandomChoice[{2, 4, 6, 8}]]}], {100000}];
values = {0, 2, 4, 6, 8} // Developer`ToPackedArray;
(r1 = Pick[ConstantArray[Range@Length@lists, Length@values], 
           ConstantArray[
             func /@ lists // Developer`ToPackedArray,
             Length@values
           ] - values, 0
      ]); // AbsoluteTiming (* my attempt to vectorize kglr's solution *)

(* kglr's solution as is *)
(r2 = Pick[Range@Length@lists, # - func /@ lists, 0] & /@ values); // AbsoluteTiming

(* my approach *)
(r3 = Lookup[PositionIndex[func /@ lists // Developer`ToPackedArray], values, {}]); // AbsoluteTiming

r1 === r2 === r3
{0.0450857, Null}
{0.122854, Null}
{0.0340838, Null}
True

I suggest that instead of {L0, L2, L4, L6, L8} you use {lq[0], lq[2], lq[4], lq[6], lq[8]}.

My approcach

lq = GroupBy[
 MapIndexed[{##} &, L]
 , Q@*First -> Last@*Last
 ]

But I have to admit that @Kuba's is the best solution to my taste

lq = PositionIndex[Q /@ L]