0

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
  • I understand you are looking for a way to execute some action in the future, can you provide a more concise example, a dataset and the expected result ? Commented Sep 27, 2023 at 3:13
  • @brk in the above example, the final collection/array should be [2]. I don't think an actual dataset is needed here but sure I will edit and give an example. Commented Sep 27, 2023 at 3:16

2 Answers 2

0

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

Sign up to request clarification or add additional context in comments.

2 Comments

This correctly defer the whole function but the issue I am having is the smaller functions like filter and map. In your case, when executing the function returned by deferFn, the 4 methods are executed one by one, each would make a new array.
For example, in C#, calling arr.Where(q => q < 2) would result in an IEnumerable<int> (not int[]), which is something similar to Javascript's generator function. Therefore, further function calls also work with that generator instead of actually allocate and populate a whole new array.
-1

try this

var result = a.filter(x=>x<2).map(x=>x+1)

Refer this [link][1]

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.