vito
vito

Reputation: 515

List traversal with two adjacent elements in a Functional way

I'm trying to implement functional version of the below code

 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;
  }

i have come with the following version

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);

Are any any other simple solution to the above?

Can we avoid the default result value parameter and if condition check from the above function?

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

Upvotes: 0

Views: 218

Answers (3)

John Swindin
John Swindin

Reputation: 79

The following code maybe what you require or can be adapted for your required solution.

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 ]

Upvotes: 0

bamse
bamse

Reputation: 4373

Another approach would be to use converge on the array without the last element and the array without the first element.

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));

Your JSBin uses Ramda 0.8.0. Things have changed in the current version 0.24.1.

Upvotes: 0

Scott Christopher
Scott Christopher

Reputation: 6516

One approach would be to create a sliding window of adjacent elements using R.aperture. Then for a bit of extra sugar someComplexFn can be wrapped with R.apply to convert the binary function into one that accepts an array of two elements.

Your example would then look something like:

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

Upvotes: 3

Related Questions