简体   繁体   中英

Passed function as param should use another param from the same call

I'm recreating the filter, map, find functions in js. And I have a function pipe , that takes the given array and passes it trough an array of functions such as filter, map etc.

These are my functions:

const filter = (arr, callback) => {
  let newArr = [];
  let j = 0;
  for (let i = 0; i < arr.length; i++) {
    if (callback(arr[i])) {
      newArr[j] = arr[i];
      j++;
    }
  }
  return newArr;
};

const map = (arr, callback) => {
  let newArr = [];
  for (let i = 0; i < arr.length; i++) {
    newArr[i] = callback(arr[i], i);
  }
  return newArr;
};

const pipe = (arr, callbacks) => {
  console.log(arr, "arr");
  console.log(callbacks, "callbacks");
};

I can use filter like so, and the function works fine.

const arr = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']

filter(arr, item => item.length > 6) // returns ["exuberant", "destruction", "present"] 

However, when using pipe, I should not pass arr to each function. Instead filter and map should somehow take arr from pipe. But since those functions are being called directly in the pipe call, I do not see how can I achieve that functionality.

const arr = ['spray', 'limit', 'elite', 'exuberant', 'destruction']

pipe(
  arr,
  [
    filter(item => item.length > 6), // returns ["exuberant", "destruction"]
    map((item, index) => ({ id: index, name: item })) // returns [{ id: 0, name: 'exuberant' }, { id: 1, name: 'destruction' }]
  ]
)

// pipe returns [{ id: 0, name: 'exuberant' }, { id: 1, name: 'destruction' }]

Usually filter and map takes 2 params, arr and a callback . But in pipe it takes just the callback.

Any help would be appreciated. Thanks.

I see that you are trying to implement a concept of functional programming known as pipe .

There's a better way to do what you are trying to achieve.

Instead of passing the array to the pipe function, only pass the map and filter functions to the pipe function and have pipe function return another function that takes the input array and returns the result of executing each function from left to right and passing the input array to each function.

Also change map and filter functions to return another function that takes in the input array as an argument and returns a new array after iterating over the array and passing each each element to the callback function.

 const filter = callback => { return (arr) => { let newArr = []; let j = 0; for (let i = 0; i < arr.length; i++) { if (callback(arr[i])) { newArr[j] = arr[i]; j++; } } return newArr; }; }; const map = callback => { return (arr) => { const newArr = []; for (let i = 0; i < arr.length; i++) { newArr[i] = callback(arr[i], i); } return newArr; }; }; const pipe = (...funcs) => { return array => { return funcs.reduce((acc, curr) => curr(acc), array); }; }; const arr = ['spray', 'limit', 'elite', 'exuberant', 'destruction']; const result = pipe( filter(item => item.length > 6), map((item, index) => ({ id: index, name: item })) )(arr); console.log(result);

there is no easy solution for this since you call the function filter and map directly in the pipe creation (simple functions will execute then)

one thing you can do is change your filter and map functions so they return an object with a method.execute that needs to be called to execute the filter or the map

const filter = (callback) => {
  function execute (arr) = {
    let newArr = [];
    let j = 0;
    for (let i = 0; i < arr.length; i++) {
      if (callback(arr[i])) {
        newArr[j] = arr[i];
        j++;
      }
    }
    return newArr;
  }
  return { // return the object ready to execute
    execute
  }
};

const map = (callback) => {
  function execute (arr) {
    let newArr = [];
    for (let i = 0; i < arr.length; i++) {
      newArr[i] = callback(arr[i], i);
    }
    return newArr;
  }
  return {
    execute
  }
};

now if you want to use a filter, do

const arr = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']

filter(item => item.length > 6).execute(arr) 
// returns ["exuberant", "destruction", "present"] 

and now the pipe function

const pipe = (arr, callbacks) => {
  for (let i = 0; i < callbacks.length; i++) {
    callback.execute(arr)
  }
};

now use the pipe as wanted

const arr = ['spray', 'limit', 'elite', 'exuberant', 'destruction']

pipe(
  arr,
  [
    filter(item => item.length > 6),
    map((item, index) => ({ id: index, name: item })) 
  ]
)
// returns [{ id: 0, name: 'exuberant' }, { id: 1, name: 'destruction' }]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM