以函数式方式遍历两个相邻元素的列表

List traversal with two adjacent elements in a Functional way

我正在尝试实现以下代码的功能版本

 const adjacent = (list)  => {
    let results = [];
    for (let idx = 0; idx < list.length - 1; idx++) {
      const computedRes = someComplexFn(list[idx], list[idx + 1]);
      results.push(computedRes );
    }
    return results;
  }

我有以下版本

const locations = [1,2,3,4,5];
const calcRatioFn = (x, y) => x+y;

const adjacentMap = (list, result=[]) => {
  if(R.length(list) < 2) {
    return result;
  }
  const f1 = R.head(list);
  const f2 = R.tail(list);
  result.push(calcRatioFn(f1 ,R.head(f2)));

  return adjacentMap(R.tail(list), result);
}


const results = adjacentMap(locations);
console.log(results);

对于上述问题还有其他简单的解决方案吗?

我们可以避免使用默认结果值参数和 if 条件检查上面的函数吗?

JSBin Link http://jsbin.com/veyihepulu/1/edit?html,js,console

一种方法是创建相邻元素的滑动 window,使用 R.aperture. Then for a bit of extra sugar someComplexFn can be wrapped with R.apply 将二元函数转换为接受两个元素数组的函数。

您的示例将类似于:

const adjacentMap = R.pipe(R.aperture(2), (R.map(R.apply(someComplexFn))))

另一种方法是对没有最后一个元素的数组和没有第一个元素的数组使用 converge

let locations = [1,2,3,4,5];
const calcRatio = (x, y) => x+y;

// adjacentMap :: Array -> Array
const adjacentMap = R.converge(
    R.zipWith(calcRatio), 
    [ R.init, R.tail]
);

// saveAdjacentMap :: Array -> Array
const saveAdjacentMap = R.cond([
    [R.compose(R.lt(1), R.length), adjacentMap ],
    [R.T, R.identity]
]);

console.log(saveAdjacentMap(locations));

您的 JSBin 使用 Ramda 0.8.0。当前版本发生了变化 0.24.1.

以下代码可能是您需要的,或者可以根据您需要的解决方案进行调整。

const fn = (acc, c, i, a) => {
  return !(a[i + 1]) 
    ? acc
    : acc.concat(c + a[i + 1])
}

const _adjacentMap = (fn, list) => {
  return list.reduce(fn, [])
}

const locations = [1,2,3,4,5]

const result = _adjacentMap(fn, locations)

console.log(result)
// => [ 3, 5, 7, 9 ]