Select sub-lists of common length from a list

Revised Question

I have a list with nested lists with the following format:

lis =
{{1, 2, a}, {2, 3, a}, {4, 3, a},
{5, 4, b}, {8, 9, b}, {3, 8, b}, {1, 9, b},
{3, 5, c}, {2, 2, c}}

I would like to cut the number of nested lists with the same identifier (here a,b,c) to the length of the nested lists (type a,b,c) with the least number of nested lists. Backgroud: these lists include stock data and I have to adjust the number of data to compare them.

I would like to get a list as follows:

lis =
{{1, 2, a}, {2, 3, a},
{5, 4, b}, {8, 9, b},
{3, 5, c}, {2, 2, c}}

I use the function

numberOfNestedLists =
Min[
Map[
Count[lis1, #, 2] &,{a, b, c}]];

to get the length of the nested list type (a,b or c) with the least nested lists.

But I do not know how to cut the nested lists.

• Try this:-dataproc[lst_, key_] := Module[ {sel, len, tm, tms}, sel = len = key; Do[ tmk = key[[js]]; tms = Select[lst, SameQ[#[], tmk] &]; sel[[js]] = tms; len[[js]] = Length@tms, {js, Length@key} ]; Do[ sel[[js]] = If[SameQ[Length@sel[[js]], Min@len], sel[[js]], RandomSample[sel[[js]], Min@len] ], {js, Length@key} ]; Partition[Flatten@sel, 3] ] dataproc[lis, {a, b, c}] – dwa Mar 30 '15 at 7:48
• This question should be released from hold. At least m_goldberg and I understand the question as edited by m_goldberg. – Taiki Mar 30 '15 at 12:04

Here is just one of many ways to do what you are asking. It uses an association, so it only works in V10.

data = {{1, 2, a}, {2, 3, a}, {4, 3, a},
{5, 4, b}, {8, 9, b}, {3, 8, b}, {1, 9, b},
{3, 5, c}, {2, 2, c}};

assoc = GroupBy[data, #[] &]
<|a -> {{1, 2, a}, {2, 3, a}, {4, 3, a}},
b -> {{5, 4, b}, {8, 9, b}, {3, 8, b}, {1, 9, b}},
c -> {{3, 5, c}, {2, 2, c}}|>
Take[#, Min @@ Length /@ assoc] & /@ assoc // Values
{{{1, 2, a}, {2, 3, a}}, {{5, 4, b}, {8, 9, b}}, {{3, 5, c}, {2, 2, c}}}

Here is another that should work in earlier versions.

gathered = GatherBy[data, #[] &]
{{{1, 2, a}, {2, 3, a}, {4, 3, a}},
{{5, 4, b}, {8, 9, b}, {3, 8, b}, {1, 9, b}},
{{3, 5, c}, {2, 2, c}}}
Take[#, Min @@ Length /@ gathered] & /@ gathered
{{{1, 2, a}, {2, 3, a}}, {{5, 4, b}, {8, 9, b}}, {{3, 5, c}, {2, 2, c}}}

Revised question

My proposal for your revised question:

Needs["GeneralUtilities"]

trim[pos__][a_] := Join @@ TrimRight @ GatherBy[a, #[[pos]] &]

If you are not using Mathematica 10 then also define(1):

TrimRight[lists_] := Take[lists, All, Min[Length /@ lists]]

Now using -1 as the Part index of your identifier:

trim[-1] @ lis
{{1, 2, a}, {2, 3, a}, {5, 4, b}, {8, 9, b}, {3, 5, c}, {2, 2, c}}

You can map trim[-1] as a function. See: Define parameterized function

Old interpretations

Your example is not valid syntax as written so it is hard to see if there is a specific complication, but I assume that you have something like:

expr = Range @ {6, 3, 14, 9, 5}
{{1, 2, 3, 4, 5, 6},
{1, 2, 3},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
{1, 2, 3, 4, 5, 6, 7, 8, 9},
{1, 2, 3, 4, 5}}

To clip every list to the same length n, assuming n is >= the length of the shorted list, you can use either:

Take[expr, All, 2]

expr[[All, ;; 2]]
{{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}}

If you wish to clip lists automatically to the length of the shortest list see:

For example:

Needs["GeneralUtilities"]

TrimRight[expr]

TrimLeft[expr]
{{1, 2, 3}, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}}

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