skip to Main Content

I know Javascript Array has map, filter and the like, and reduce can be used as a way merge them (though I really dislike the syntax, it does work). However, a simple example below can prove that it is not deferred (i.e. it is executed right away at the function call).

In C# however, LINQ functions like Where and Select do not actually execute the expression until it is needed and (to my knowledge) only a final collection is ever allocated:

var a = new int[] { 1, 2, 3 };

var b = a.Where(q => q < 2).Select(q => q + 1); // This code is not actually executed here yet
var c = b.ToArray(); // Here an array is actually allocated

// c should be [ 2 ]

In the below Javascript, I believe two arrays are actually allocated and the expression is called right away:

const a = [1,2,3];

const b = a.filter(q => { 
  console.log("filter executed");
  return q < 2;
});
console.log(b.constructor.name);

const c = b.map(q => {
  console.log("map executed")
  return q + 1;
});
console.log(c.constructor.name);
// c should be [ 2 ]

The closest I can find is the yield operator but I cannot find any built-in method that convert an array to such collection/generator.

Assuming I have a large array/collection, is there any built-in functions that defer the executions until they are actually needed?

Sometimes an operation can be like this (just an example) and defered execution may be more favorable:

var foo = bar.filter(pred1).map(q => calc(q.value)).filter(q => Boolean(q)).map(finalMap);

Here’s an example (but 4 arrays are allocated in the process):

const adjustedMultiplier = [1, 1.2, 1.5, 1.7];

const data = [
  {
    name: "Person 1",
    fromId: 1,
    score: 9,
    details: {} // More data
  },
  {
    name: "Person 2",
    fromId: 1,
    score: 6,
    details: {} // More data
  },
  {
    name: "Person 3",
    fromId: 3,
    score: 8,
    details: {} // More data
  },
  // More
];

const expectedResult = data
  .filter(q => q.fromId < 3)
  .map(q => ({
    name: q.name,
    adjustedScore: q.score * adjustedMultiplier[q.fromId]
  }))
  .filter(q => q.adjustedScore >= 8);
console.log(expectedResult);

2

Answers


  1. If I understand correctly you are looking for a higher order function. In that case you can also explore closure. In the below code a function is created which return another function. You can call the inner function whith the data and execute it whenever required

    const adjustedMultiplier = [1, 1.2, 1.5, 1.7];
    
    const data = [{
        name: "Person 1",
        fromId: 1,
        score: 9,
        details: {} // More data
      },
      {
        name: "Person 2",
        fromId: 1,
        score: 6,
        details: {} // More data
      },
      {
        name: "Person 3",
        fromId: 3,
        score: 8,
        details: {} // More data
      }
    ];
    
    
    function deferFn() {
      return function(val) {
        return data
          .filter(q => q.fromId < 3)
          .map(q => ({
            name: q.name,
            adjustedScore: q.score * adjustedMultiplier[q.fromId]
          }))
          .filter(q => q.adjustedScore >= 8);
      }
    
    }
    const expectedResult = deferFn()
    console.log(expectedResult); // this will not execute the function
    console.log(expectedResult(data)) // this will execute the function
    Login or Signup to reply.
  2. try this
    
    var result = a.filter(x=>x<2).map(x=>x+1)
    
    Refer this [link][1]
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search