【发布时间】:2017-01-19 13:07:36
【问题描述】:
我有一个场景,标准的 List.groupBy 函数不是我想要的,但我不知道该函数的正确名称,因此很难搜索。
我有一个'T 类型的项目列表和一个'T -> 'k 密钥生成函数。这些项目已经在列表中“分组”在一起,因此当您通过 key 函数映射列表时,其结果往往会在同一行中多次出现相同的键,例如[1; 1; 1; 2; 2; 1; 1; 3; 3; 3; 1; 1]。我想要的是获得一个列表列表,其中内部列表包含键生成函数返回相同值的所有项目 - 但它不应该将不同的 1 序列组合在一起。
换句话说,假设我的数据是一个字符串列表,生成密钥的函数是String.length。所以输入是:
["a"; "e"; "i"; "to"; "of"; "o"; "u"; "and"; "for"; "the"; "I"; "O"]
我正在寻找的输出是:
[["a"; "e"; "i"]; ["to"; "of"]; ["o"; "u"]; ["and"; "for"; "the"]; ["I"; "O"]]
换个角度想:这就像获取列表的第一项并存储调用键函数的结果。然后您将使用takeWhile (fun x -> keyFun x = origKeyFunResult) 生成第一段。然后,当 takeWhile 停止返回值时,您记录它停止的时间,并在第一个没有返回原始结果的值上记录 keyFun x 的值——然后从那里继续。 (除了那将是 O(N*M) ,其中 M 是序列的数量,并且在许多情况下会演变为 O(N^2) - 而应该可以在 O(N) 时间内实现此功能)。
现在,我可以很容易地编写那个函数了。那不是问题。我想知道这个函数是否有一个标准的name。因为我认为它会被称为groupBy,但那是另一回事。 (List.groupBy String.length 将返回 [(1, ["a"; "e"; "i"; "o"; "u"; "I"; "O"]); (2, ["to"; "of"]), (3, ["and"; "for"; "the"])],但在这种情况下,我希望“a/e/i”、“o/u”和“I/O”列表保持分离,但我不这样做希望键生成返回的值在输出数据中)。
也许这个函数没有标准名称。但如果有,那是什么?
【问题讨论】:
-
我认为没有标准名称。你应该继续写这个;您已经说过它很容易编写,并且您为该函数编写的代码将用于记录它的作用。
-
另见groupAdjBy,它类似于您的函数,但通用,我的意思是它适用于数组、列表和序列。
-
GroupAdjacent in MoreLINQ 也是如此。
-
把它命名为
chunk或chunkBy,因为与List.chunkBySize相似。两者都创建一个列表列表,保留原始列表的顺序,另一个按大小分块,另一个按谓词分块。