After some thinking, it occurred to me that functionality of the built-in BinLists could be transferred to a user-defined BinListsBy if BinLists itself was used in the implementation.
The function BinListsBy defined below will bin the first level items in data using the values obtained when the the function f is applied to each item. BinListsBy[data,f,options] accepts 2 arguments and an optional sequence of options. f is a function. When f is mapped onto the first level of data it must return a list of values acceptable to BinLists. options is an optional sequence of options which will be passed directly to BinLists. The built-in function BinLists does the real work. (An attached notebook contains the function and examples.)
EDIT: Function modified and file replaced
Define the BinListsBy function
BinListsBy[data_, f_, opts___] := Module[{binBy, binning, select},
(* function f must return a list acceptable to BinLists *)
binBy = f /@ data;
(* construct bins of binBy values *)
binning = Union/@BinLists[binBy, opts];
(* selects data elements for which f[element] is in a list *)
select[l_] := Select[data, MemberQ[l, f[#]] &];
(* use select to bin the original data according to the binning \
lists *)
select /@ binning
]
Make up some strings as data
In[11]:= data = Table[
StringJoin@
Table[FromLetterNumber[
RandomInteger[{1, 26}]], {RandomInteger[{3, 7}]}],
{100}
]
Out[11]= {"kyiixs", "yblgx", "hjjwffz", "fhmt", "cmdgq", "czya", \
"tirnp", "ykajxq", "qyjgpf", "voge", "dxghgt", "fexr", "bueexkv", \
"yunxf", "ysbf", "pilpc", "mzsolsq", "dtixsu", "qpfzr", "xlqe", \
"mskqarr", "brqeyg", "zmrrs", "czhgqw", "shx", "iiwu", "rwcwnge", \
"piwix", "wdprv", "vpluzh", "bfherb", "pzqb", "fbvhvd", "wzr", \
"ghviirv", "pds", "fwfaogx", "hljp", "uda", "npmh", "cerfxpo", \
"cdkk", "vspiq", "qwxrly", "xxenpd", "ivwvitr", "fgio", "agki", \
"hkcvouh", "jafsf", "resj", "cgrphv", "bqyqvhe", "eutp", "qwhmjzz", \
"dubopa", "xqh", "yglbfg", "ods", "mfgmcg", "ufokyy", "wkrauf", \
"vyccac", "kioicj", "pnavibb", "izhiekh", "ypvlstb", "hkkszt", \
"vixrt", "nhtjky", "fdayiml", "aiy", "efzzu", "vbjpcvv", "uruykdr", \
"zchwbj", "mdhfdqn", "aduvvjc", "xub", "lyb", "xrjmfi", "buxdt", \
"znirgo", "lgfab", "faxnq", "olkph", "hswtjy", "kccmed", "ernc", \
"vfulbb", "dtd", "fomket", "sma", "ivrbog", "oaod", "oljcalq", \
"gpzfixq", "rmueo", "vlnlali", "sykvt"}
This function returns the letter number of first character in a string
In[12]:= firstCharNum[str_] := LetterNumber@Characters[str][[1]]
In[13]:= firstCharNum[data[[1]]]
Out[13]= 11
Bin data in bin widths of 3 by LetterNumber of leading character (TableForm doesn't really work in the Forum.)
In[14]:= BinListsBy[data, firstCharNum, 3] // TableForm
Out[14]//TableForm= TableForm[{{
"tirnp", "shx", "rwcwnge", "resj", "sma", "rmueo", "sykvt"}, {
"bueexkv", "brqeyg", "bfherb", "agki", "bqyqvhe", "aiy", "aduvvjc",
"buxdt"}, {
"kyiixs", "iiwu", "ivwvitr", "jafsf", "kioicj", "izhiekh", "kccmed",
"ivrbog"}, {
"mzsolsq", "mskqarr", "npmh", "mfgmcg", "nhtjky", "mdhfdqn", "lyb",
"lgfab"}, {
"cmdgq", "czya", "dxghgt", "dtixsu", "czhgqw", "cerfxpo", "cdkk",
"cgrphv", "eutp", "dubopa", "efzzu", "ernc", "dtd"}, {
"qyjgpf", "pilpc", "qpfzr", "piwix", "pzqb", "pds", "qwxrly",
"qwhmjzz", "ods", "pnavibb", "olkph", "oaod", "oljcalq"}, {
"voge", "wdprv", "vpluzh", "wzr", "uda", "vspiq", "ufokyy",
"wkrauf", "vyccac", "vixrt", "vbjpcvv", "uruykdr", "vfulbb",
"vlnlali"}, {
"yblgx", "ykajxq", "yunxf", "ysbf", "xlqe", "zmrrs", "xxenpd",
"xqh", "yglbfg", "ypvlstb", "zchwbj", "xub", "xrjmfi", "znirgo"}, {
"hjjwffz", "fhmt", "fexr", "fbvhvd", "ghviirv", "fwfaogx", "hljp",
"fgio", "hkcvouh", "hkkszt", "fdayiml", "faxnq", "hswtjy",
"fomket", "gpzfixq"}}]
Attachments: