Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map array items through several functions

Is there a more elegant way then this to execute several functions in succession for each item in the array:

type Transform<T> = (o: T) => T;
type Item = { /* properties */ };

transform(input, transformers: Transform<Item>[]) {
  const items: Item[] = getItems(input);
  return items.map(item => {
    let transformed = item;
    tramsformers.forEach(t => transformed = t(transformed));
    return transformed;
  })
}
like image 848
Sasxa Avatar asked Aug 27 '17 09:08

Sasxa


People also ask

How do you map an array of objects?

The syntax for the map() method is as follows: arr. map(function(element, index, array){ }, this); The callback function() is called on each array element, and the map() method always passes the current element , the index of the current element, and the whole array object to it.

How do you map an array of arrays?

map() creates a new array from calling a function for every array element. map() calls a function once for each element in an array. map() does not execute the function for empty elements. map() does not change the original array.

Can you map an array?

JavaScript | Array map() Method The map() method in JavaScript creates an array by calling a specific function on each element present in the parent array. It is a non-mutating method. Generally map() method is used to iterate over an array and calling function on every element of array.

What is the difference between the map () and the forEach () method on the array prototype Mcq?

The main difference between map and forEach is that the map method returns a new array by applying the callback function on each element of an array, while the forEach method doesn't return anything. You can use the forEach method to mutate the source array, but this isn't really the way it's meant to be used.


1 Answers

This is a great use case for reduce:

transform(input, transformers: Transform<Item>[]) {
  const items: Item[] = getItems(input);
  return items.map(item => transformers.reduce((val, transformer) => transformer(val), item));
}

Or perhaps more readably:

transform(input, transformers: Transform<Item>[]) {
  const items: Item[] = getItems(input);
  return items.map(
    item => transformers.reduce(
      (val, transformer) => transformer(val),
      item
    )
  );
}

Live Example:

function getItems(input) {
  return [
    "abcdefg",
    "1234567"
  ];
}
function transform(input, transformers) {
  const items = getItems(input);
  return items.map(item => transformers.reduce((val, transformer) => transformer(val), item));
}
const result = transform("x", [
  v => v.toUpperCase(),
  v => v.substring(1, v.length - 1)
]);
console.log(result);

As Nitzan Tomer points out, we could do away with the items constant:

transform(input, transformers: Transform<Item>[]) {
  return getItems(input).map(
    item => transformers.reduce(
      (val, transformer) => transformer(val),
      item
    )
  );
}

I frequently keep those sorts of things for debugging, but some good debuggers now make it easy to see the return value of functions before they return (Chrome's does), so if you removed it, you could step into getItems to see the items before the map.

like image 100
T.J. Crowder Avatar answered Oct 05 '22 18:10

T.J. Crowder