Why Does Array#Each Return an Array with The Same Elements

Why does Array#each return an array with the same elements?

Array#each returns the [array] object it was invoked upon: the result of the block is discarded. Thus if there are no icky side-effects to the original array then nothing will have changed.

Perhaps you mean to use map?

p [1,2,3,4,5].map { |i| i*i }

Create an array with same element repeated multiple times

You can do it like this:

function fillArray(value, len) {
if (len == 0) return [];
var a = [value];
while (a.length * 2 <= len) a = a.concat(a);
if (a.length < len) a = a.concat(a.slice(0, len - a.length));
return a;
}

It doubles the array in each iteration, so it can create a really large array with few iterations.


Note: You can also improve your function a lot by using push instead of concat, as concat will create a new array each iteration. Like this (shown just as an example of how you can work with arrays):

function fillArray(value, len) {
var arr = [];
for (var i = 0; i < len; i++) {
arr.push(value);
}
return arr;
}

How are array.each and array.map different?

The side effects are the same which is adding some confusion to your reverse engineering.

Yes, both iterate over the array (actually, anything that mixes in Enumerable) but map will return an Array composed of the block results while each will just return the original Array. The return value of each is rarely used in Ruby code but map is one of the most important functional tools.

BTW, you may be having a hard time finding the documentation because map is a method in Enumerable while each (the one method required by the Enumerable module) is a method in Array.

As a trivia note: the map implementation is based on each.

Array#each vs. Array#map

Array#each executes the given block for each element of the array, then returns the array itself.

Array#map also executes the given block for each element of the array, but returns a new array whose values are the return values of each iteration of the block.

Example: assume you have an array defined thusly:

arr = ["tokyo", "london", "rio"]

Then try executing each:

arr.each { |element| element.capitalize }
# => ["tokyo", "london", "rio"]

Note the return value is simply the same array. The code inside the each block gets executed, but the calculated values are not returned; and as the code has no side effects, this example performs no useful work.

In contrast, calling the array's map method returns a new array whose elements are the return values of each round of executing the map block:

arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]

Can a loop create a new, different array each time it runs?

This depends on what exactly you want to do. In your example, you will create 10 individual and seperate arrays, but maybe their use is not so helpful because:

for(int i = 0; i < 10; i++)
{
int arrayi[5] = {0}; // The array is created here.
} // The array goes out of scope and is destroyed here. It can't be used in the next
// iteration of the for loop.
// You can't use any of the arrays created here.

Maybe this is what you want, if you want to use the array in the for loop for example.

Maybe you want the array to stick around so you can use it after. Then you have 2 choices:

  1. Make a 2d array:

int arr[10][5]; // Use by indexing eg arr[4][1] is the second 
// element of the fifth array.
// or
int arr[50]; // A flat packed array, usually accessed via
// index: row*rowlength + colomn

  1. Define each of the arrays as a seperate named object (very rare that this is required):

int arrForUse[5];
int arrForDifferentUse[7];
...
int arrXXX[15];

If the arrays are truely used for different things and are not related at all this is what you will do. They will not be named arr1, arr2, ... though.

Why does this 'fold array' function return less elements than expected?

Your problem is that you're modifying the input array, which Codewars is reusing in multiple test cases. Do something like arr = array.dup as the first line of your function, and then change all subsequent occurrences of array in your code to arr (or whatever variable name you chose) and then you should be fine.

Loop (for each) over an array in JavaScript

TL;DR

  • Your best bets are usually

    • a for-of loop (ES2015+ only; spec | MDN) - simple and async-friendly
      for (const element of theArray) {
      // ...use `element`...
      }
    • forEach (ES5+ only; spec | MDN) (or its relatives some and such) - not async-friendly (but see details)
      theArray.forEach(element => {
      // ...use `element`...
      });
    • a simple old-fashioned for loop - async-friendly
      for (let index = 0; index < theArray.length; ++index) {
      const element = theArray[index];
      // ...use `element`...
      }
    • (rarely) for-in with safeguards - async-friendly
      for (const propertyName in theArray) {
      if (/*...is an array element property (see below)...*/) {
      const element = theArray[propertyName];
      // ...use `element`...
      }
      }
  • Some quick "don't"s:

    • Don't use for-in unless you use it with safeguards or are at least aware of why it might bite you.
    • Don't use map if you're not using its return value.
      (There's sadly someone out there teaching map [spec / MDN] as though it were forEach — but as I write on my blog, that's not what it's for. If you aren't using the array it creates, don't use map.)
    • Don't use forEach if the callback does asynchronous work and you want the forEach to wait until that work is done (because it won't).

But there's lots more to explore, read on...


JavaScript has powerful semantics for looping through arrays and array-like objects. I've split the answer into two parts: Options for genuine arrays, and options for things that are just array-like, such as the arguments object, other iterable objects (ES2015+), DOM collections, and so on.

Okay, let's look at our options:

For Actual Arrays

You have five options (two supported basically forever, another added by ECMAScript 5 ["ES5"], and two more added in ECMAScript 2015 ("ES2015", aka "ES6"):

  1. Use for-of (use an iterator implicitly) (ES2015+)
  2. Use forEach and related (ES5+)
  3. Use a simple for loop
  4. Use for-in correctly
  5. Use an iterator explicitly (ES2015+)

(You can see those old specs here: ES5, ES2015, but both have been superceded; the current editor's draft is always here.)

Details:

1. Use for-of (use an iterator implicitly) (ES2015+)

ES2015 added iterators and iterables to JavaScript. Arrays are iterable (so are strings, Maps, and Sets, as well as DOM collections and lists, as you'll see later). Iterable objects provide iterators for their values. The new for-of statement loops through the values returned by an iterator:

const a = ["a", "b", "c"];
for (const element of a) { // You can use `let` instead of `const` if you like
console.log(element);
}
// a
// b
// c

Lucee array.each return value

You need to look slightly closer at the code in your first example:

public function getLineItemDetailsById(required numeric id){ // first function
this.LineArray.each(function(i){ // second function
if(i.Id == id){
return i; // return for second function
}
});
// no return from first function
}

I have annotated it slightly to demonstrate your problem. getLineItemDetailsById() "returns null" because you simply aren't returning anything from it. So if you have:

result = getLineItemDetailsById(1);

then getLineItemDetailsById() is not returning anything, so result ends up being null.

So that's the problem you're seeing.

Furthermore, you don't want to be using each() within that function: one would only use each() when you definitely want to iterate over the entire array. In your case it seems like you want to exit as soon as you find a match for id.

In which case you want something like this:

public function getLineItemDetailsById(required numeric id){
var matchedElement = null;
this.LineArray.some(function(element){
if(element.Id == id){
matchedElement = element;
return true;
}
});
return matchedElement;
}

One uses some() when one wants to iterate over an array only until some criteria is matched. Here I'm leveraging this to set the matchedElement when the exit criteria is met.



Related Topics



Leave a reply



Submit