Q:

Gathering a List efficiently

In my situation, I have a large list of objects L={A,B,C,D,E,...}
and a function Q[] applying to them, which will produce the values only from the set {0,2,4,6,8}. 
(e.g. Q[] can be Length[] and my objects ABCDE are lists of certain sizes)
I want to split the list so that I will obtain 5 lists L0,L2,L4,L6,L8, each list contains only the index of the corresponding elements in L (Because I want to keep track of the location of those objects in the original list).
Is there an effective way to do this, other than doing a for loop if statement and calling AppendTo[] adding the index each time?
(The Mathematica function GatherBy[] will only give the element of the list itself, but not the index in the original list which I want.)
For example, for the input list
L={{1,2},{3,4,5,6},{7,8,9,10},{11,12}}

and
Q=Length

I want
{L0,L2,L4,L6,L8} = {{},{1,4},{2,3},{},{}}

since sublists of length 2 are at positions 1 and 4, length 4 -- at 2 and 3, and there are no sublists of length 0, 6, 8.

A:

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

A:

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

A:

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]

