View Problem

Categorise a list

Given the list [one, two, three, four, five] produce a map {3:[one, two], 4:[four, five], 5:[three]} which sorts elements into map entries based on their length
ExpandDiskEdit
ruby
lengths = {}
list.each do |x|
len = x.size
lengths[len] = (lengths[len] || [])
lengths[len] << x
end
ExpandDiskEdit
ruby 1.8.7+
lengths = list.group_by {|x| x.size}
DiskEdit
ruby ruby 1.8+
list.inject({}) { |h,x| (h[x.size]||=[]) << x; h }
ExpandDiskEdit
cpp C++/CLI .NET 2.0
for each(String^ entry in input)
{
key = entry->Length;
if (!hash->ContainsKey(key)) hash[key] = gcnew ArrayList;
safe_cast<ArrayList^>(hash[key])->Add(entry);
}
ExpandDiskEdit
fsharp
let catmap = (List.foldLeft (fun (acc : Map<int, List<string> >) (e : string) -> if (Map.mem e.Length acc) then (Map.add e.Length ((Map.find e.Length acc) @ [e]) acc) ; else (Map.add e.Length [e] acc)) (Map.empty) list)
DiskEdit
fsharp
let lengthMap =
["one"; "two"; "three"; "four"; "five"]
|> Seq.groupBy (fun s -> s.Length)
|> Seq.map (fun (length, entries) -> (length, entries |> List.ofSeq))
|> Map.ofSeq
ExpandDiskEdit
erlang
% Imperative Solution
CatList = categorise(List),
ExpandDiskEdit
erlang
% Functional (1) Solution
CatList = categorise(List),
DiskEdit
csharp .NET 3.5
using System.Collections.Generic;
using System.Linq;
public class ListCategorizer {
public static void Main() {
var list = new List<string>() { "one", "two", "three", "four", "five" };
var categories = list.GroupBy(el => el.Length)
.ToDictionary( g => g.Key, // key
g => g.ToList() ); // value
}
}
DiskEdit
haskell
import qualified Data.Map as Map

groupInMapBy :: Ord k => (a -> k) -> [a] -> Map.Map k [a]
groupInMapBy f = foldr (\a -> Map.insertWith (++) (f a) [a]) Map.empty

output :: Map.Map Int [String]
output = groupInMapBy length ["one", "two", "three", "four", "five"]
DiskEdit
haskell
import Data.List (groupBy, sortBy)
import Data.Function (on)

groupInPairsBy :: Ord k => (a -> k) -> [a] -> [(k, [a])]
groupInPairsBy f = map (\xs -> (f (head xs), xs)) .
groupBy ((==) `on` f) . sortBy (compare `on` f)

output :: [(Int, [String])]
output = groupInPairsBy length ["one", "two", "three", "four", "five"]

Submit a new solution for ruby, cpp, fsharp, erlang ...
There are 14 other solutions in additional languages (clojure, fantom, groovy, java ...)