功能编程:配对列表中的项目

时间:2014-10-05 11:30:02

标签: javascript functional-programming

我有一个数组,我想通过将项目组合在一起来重新排序。 e.g:

[1, 1, 0, 1, 0, 1, 0] => [1, 1, 0, 1, 1, 0, 0]

OR

[1, 1, 0, 1, 0, 1, 0] => [[1, 1], [0], [1, 1], [0, 0]]

在此示例中,1s已与最大组大小为2个项目组合在一起。我不想将所有项目组合在一起 - 我只想配对值。

写我的函数的最佳方法是什么?降低?分类?我正在寻找一种使用函数式编程技术的干净解决方案,如果这样可以实现更好的抽象,最好采用多个步骤。我正在使用JavaScript,但如果逻辑清晰,我会接受任何语言作为答案。

一些背景:我有一个照片列表,我想重新排序列表,以便方形照片(在我的示例中名为1)并排显示清单。

1 个答案:

答案 0 :(得分:0)

  

编写我的函数的最佳方法是什么?

可能采用强制性但纯粹的方式 - 我们正在寻找O(n)解决方案。

  

减少

好吧,基本上每个数组遍历都是某种reduce。所以我们绝对可以使用它,但它并不一定能使代码在JavaScript中更具可读性。

  

排序

没有。我们没有对您的列表进行排序。

  

我正在寻找使用函数式编程技术的干净解决方案,如果这样可以实现更好的抽象,最好采用多个步骤。我使用JavaScript但如果逻辑清晰,我会接受任何语言作为答案。

好吧,在Haskell中它可能看起来像

import Control.Arrow
import Data.Either

groupRightPairs = groupNRights 2

groupNRights :: Int -> [Either a b] -> [Either a [b]]
groupNRights 0 xs          = undefined
groupNRights n []          = []
groupNRights n (Left x:xs) = Left x : groupNRights n xs
groupNRights n xs          = uncurry (:) $ first Right $ second (groupNRights n) $ spanNRights n xs
                          {- let (rs, rest) = spanNRights n xs
                             in (Right rs) : (groupNRights n rest) -}
  where
    spanNRights :: Int -> [Either a b] -> ([b], [Either a b])
    spanNRights 0 xs = ([], xs)
    spanNRights n [] = ([], [])
    spanNRights n (Left x:xs) = second ((Left x):) (spanNRights n xs)
    spanNRights n (Right x:xs) = first (x:) (spanNRights (n-1) xs)

然而,JavaScript没有缺点列表,所以当你可以将它转换为JS时,它看起来不再那么好了(虽然没有类型限制它会变得更简单)。相反,你宁愿这样做:

function getOnePairs(arr) {
    return getOneGroups(arr, n);
}
function getOneGroups(arr, n) {
    var result = [],
        group = [];
    for (var i=0; i<arr.length; i++) {
        if (arr[i] != 1) {
            result.push(arr[i]);
        } else {
            if (group.length >= n)
                result.push(group = []);
            group.push(arr[i]); // this mutation is not very functional
        }
    }
    return result;
}