Array OverWrite itself by pushing Objects (JavaScript) - javascript

So here comes my problem: In my opinion it's a very simple problem to solve but i don't know why this is happening; well as my title say my array is overwriting itself giving as output a 7 Object's Array
Here is the code, i've put some console.log() for you to see what i'm meaning:
let str = "100 23 20 99 92 123 88";
let arr = str.split(" ");
console.log(arr);
console.log("\n");
var aObj={};
let arrS=[];
console.log(arrS);
for (let i = 0; i<arr.length;i++){
let sum=0;
for (let j=0; j<arr[i].length;j++){
sum += parseInt(arr[i][j]);
}
aObj.value=sum;
aObj.strI=arr[i];
console.log(aObj);
console.log("\n");
arrS.push(aObj);
console.log(arrS);
console.log("\n");
}
https://repl.it/#Arcall95/try#index.js

Relevant: Push is overwriting previous data in array
Every iteration of the loop, what you're doing is changing the properties of a single object aObj and pushing it to arrS.
Instead, you should be creating a new object for each iteration by pulling var aObj={} inside the loop.

Related

Duplicating array in nested array with one value change, changes entire nested array in javascript

I have an nested array. Example
let array = [['a','e1'],['b','b1']]
What i want to achive is a new nested array with a copy of one of the array's and a change to that copy.
when i run it though a loop (tried for and foreach) it duplicates the change throughout the entire nested array.
here is an example of the code (note its not key: index and just an example. the actual inside array contains 11 values in total)
let array = [['a','e1'],['b','b1']]
let result = []
for(let x of array){
result.push(x);
if(x[1]==='e1'){
let newRow = x;
newRow[1] = 'e2'
result.push(newRow);
}
}
//result: [[a,e2],[a,e2],[b,b1]]
let needResult = [['a','e1'],['a','e2'],['b','b1']]
Any assistance in this would be greatly appreciated.
Working example of the script : https://stackblitz.com/edit/js-ah1bvf?file=index.js
Thanks
Instead of use let newRow = x;, as #tadman said in the comment you need to use another way like create a new array let newRow = []; //for example
let array = [['a','e1'],['b','b1'], ['c', 'e1']]
let result = []
for(let x of array){
result.push(x);
if(x[1]==='e1'){
const newRow = [];
newRow[0] = x[0];
newRow[1] = 'e2'
result.push(newRow);
}
}
console.log(result)
As #tadman said in the comment :
let newRow = [...x] // works.
I did not select #simons answer though valid as stated in my question the array can be quite large and I don't necessarily know exactly how long it is.
Thanks for the help!

Assign a array of indexes as an object value

I have an assignment which i need to sole but i am really stuck and can't make a progress. The assignment consist in an array of elements like this
const appleHolderLine = ['Rome', 'Ambrosia', 'Rome', 'RedDelicious', 'Akane','RedDelicious', 'SweeTango', 'RedDelicious', 'RedDelicious', 'Opal', 'Winesap', 'RedDelicious', 'Empire', 'RedDelicious', 'Liberty'];
Firstly it is needed to declare a variable lineCount which count for every element of the array and a reference to an object called appleMap.
Than the challenge consist in looping through the array and the elements of the array would be the object keys with no duplicates and the values would be an array of idexes of the specific element place of the array. To give an example how it should look like:
Example:
const appleHolderLine = ['GreenApples', 'RedDelicious','OrangeApples', 'PurpleApples', 'RedDelicious']
console.log (lineCount, appleMap)
Should Log:
5, {'GreenApples':[0], 'RedDelicious': [1,4], 'OrangeApples':[2], 'PurpleApples': [3]}
My progress so far
var lineCount = 0;
var appleMap = {};
for (let i = 0; i < appleHolderLine.length; i++){
lineCount++;
// if element in the array exist in the array
appleMap[appleHolderLine[i]] = [i];
}
Could you give me a hint of how to solve this, i am really stuck.
Basically you can create an empty array the first time and keep pushing like below
var lineCount = 0;
var appleMap = {};
for (let i = 0; i < appleHolderLine.length; i++){
lineCount++;
if(!appleMap[appleHolderLine[i]])
appleMap[appleHolderLine[i]] = []
appleMap[appleHolderLine[i]].push(i);
}
You could use Array.prototype.reduce which is a more advanced construct javascript provides. Please refer to answer by CodeManiac below for the same.
The above answer is to clarify the basic idea and hint on how you could think
Also, lineCount can be obtained by using appleHolderLine.length directly.
You don't need an extra variable ( Line count ) here, simply loop over the value use, use the index to access value, check if there's nothing present for that key then just initialize it with empty array, push index to the key in each iteration
const appleHolderLine = ['GreenApples', 'RedDelicious','OrangeApples', 'PurpleApples', 'RedDelicious']
var appleMap = {};
for (let i = 0; i < appleHolderLine.length; i++){
if(!appleMap[appleHolderLine[i]]){
appleMap[appleHolderLine[i]] = []
}
appleMap[appleHolderLine[i]].push(i);
}
console.log(appleMap)
You can simply use reduce
const appleHolderLine = ['GreenApples', 'RedDelicious','OrangeApples', 'PurpleApples', 'RedDelicious']
let final = appleHolderLine.reduce((op,inp,i)=>{
op[inp] = op[inp] || []
op[inp].push(i)
return op
},{})
console.log(final)
Line count is simply same as length of array, let lineCount = appleHolderLine.length
I suppose, the shortest answer is the functional one.
const appleHolderLine = ['GreenApples', 'RedDelicious','OrangeApples', 'PurpleApples', 'RedDelicious']
result = appleHolderLine.reduce((a,c,i) => { if(a[c]) a[c].push(i); else a[c]=[i]; return a; }, {})
console.log(result)
But I am not sure that you are expected to deliver a functional solution. Still, you might find it useful. The idea is that the reduce method starts with an empty object and iterates through the array. In each iteration, it checks if the current element c is already a field of the accumulator a. If so adds its index i to the specific field, if not, initializes the field with the current element as name and the index as a single-element array as value.

Array only being updated on first iteration of a for loop

The following code takes an array of objects structured like so: {html:whatever number:number value}.
function Org(data){
//array of objects
var Data=data;
for(var i=0; i<Data.length; i++){
var nums=[];
nums.push(Data[i].number);
console.log(nums);}
}
Nums should have be logged to the console as [1,1] on the second iteration when called with: [{html:null,number:1},{html:null,number:1}] but instead is logged as [1] on both the first and second iterations. Why might this be?
You need to move the initialization of num outside of the for loop. Inside it creates for each iteration a new empty array.
BTW, no need for using another variable for data.
function Org(data){
var nums = [];
for (var i = 0; i < data.length; i++){
nums.push(data[i].number);
}
console.log(nums);
}
Or shorter:
var Org=data=>console.log(data.map(e=>e.number));

Basic For Loop Logic Doesn't make sense to me

I've been trying to learn Javascript for the longest time, and it is kind of frustrating. I'm back to learning the basics again, and I was playing around with these for loops and arrays below.
Can someone please explain why the output of this code is [1,2,3,4,5] and not [6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]?
var game1 = new Array();
for(i = 25; i > "love is like a river".length; i = i - 1) {
console.log(game1.push(i));
}
console.log(game1.push(i));
What this statement does is it prints to the console the index of the element being pushed. The result 1,2,3,4,5 is the length of the array.
What you want to code is:
var game1 = [];
for(i = 25; i > "love is like a river".length; i--){
console.log(i);
game1.push(i);
}
in the above example I switched the declaration of the array, because this is the most common way(this is not necessary).It will still work normally with your version of declaration. In the for loop I've switched
i = i - 1;
to shorthand version:
i-- or --i
which decrements ' i ' by 1. Also I've separated
console.log(i) and game1.push(i) to be separate
this will print out the result of ' i ' : 25,24,23,22,21
this is because the for loop does the action that the users defines at the end of the loop, so when the loop prints out 21 and pushes it to the array, it decrements to 20, at which the loop stops. The array will still have the numbers 25,24,23,22,21. but the console will not log it.
if you want the output you defined above you would have to:
var game1 = [];
for(i = 6;i >= 25; i++){
game1.push(i);
console.log(game1[i-6]);
}
in this you add ' i ' to game1 resulting in [6,7,8,9,10,11,12,13,14...25] and you log the variable at the index of ' i - 6'. This will result in the number int he square brackets being "0,1,2,3,4,5" starting at 0 because that is where all arrays indexs start at.
The length property returns the length of a string (number of characters). In this way "love is like a river".length gives 20. I think you mistook it as no. of words. The loop will then behave like
var game1 = new Array();
for(i = 25;i>20;i=i-1){
console.log(game1.push(i));
}
To get your expected answer the code would be:
var game1 = new Array();
for(i = 25;i>"love is like a river".length;i=i-1){
console.log(game1.push(i));
}
You are getting the expected [25, 24, 23, 22, 21] as the result for game1!
The 1, 2, 3, … you are seeing are the results of the Array push calls that you are logging, which yield the length of the array each time.
The "love is like a river".length is 20. So the loop is equivalent to this:
for(i = 25; i>20; i=i-1){
}
That being said, you have 5 calls of the console.log passing to it the following arguments one at each for step:
game1.push(25)
game1.push(24)
game1.push(23)
game1.push(22)
game1.push(21)
Not knowing exactly what game1.push does, it's hard to tell. However, supposing that game1 is an array, you would get at each push the new length of the array.
According to MDN:
The push() method adds one or more elements to the end of an array and
returns the new length of the array.
"love is like a river".length is 20, so you will start from i=25 until i=21.
[1,2,3,4,5] represents the length of game1 for each loop.
To see the game1 value:
for(i=0; i<game1.length; i++) {
console.log(game1[i]);
}
Result: [25,24,23,22,21]
Lets start by breaking down your code, beginning with the new Array() constructor that you stored in the variable game1.
var game1 = new Array();
At this point, all you have is an empty array, which has been stored in a variable to be used at a later time. Incidentally, this is the equivalent of the array literal: var game1 = [].
Lets step through to the next portion of your code, which is a for() loop:
for (i = 25; i > "love is like a river".length; i--) {}
This loop initializes at the upper bound of 25 and decrements down to a lower bound bound of 20 which is set by the length() property condition of the string. Within this loop you have the statement:
console.log(game1.push(i));
The method push() adds an element or elements to the end of an array and returns the new length of the array to the stack. This method relies on the length property to determine its injection point. So, before the iteration, the game1 stack is currently at 0 since you never populated the array with any values. As you perform the iteration, push() method will add to the stack an undefined value on each step, there by increasing the array length by 1.
This can be illustrated by calling your game1 variable with a single numeric argument, which will set the initial size of the array. Here is an example:
var string = 'love is like a river';
var game1 = new Array(15);
for (i = 25; i > string.length; i--) {
console.log(game1.push(1));
}
As you can see, I passed the numeric argument 15 to the new Array() constructor which set the initial game1 length stack to 15. Since we are decrementing from 25 (i = 25) to 20 (string.length) we iterate 5 times, producing the expected result: [16, 17, 18, 19, 20].
If you are looking for an outcome of [6, 7, 8,...,25] you can can adjust your for() loop incrementing as opposed to decrementing and set the intitializer to 6. Here is what it will look like:
var s = "love is like a river";
for (i = 6; i <= s.length + 5; i++) {
console.log(i);
}

JavaScript Array

I usually script/program using python but have recently begun programming with JavaScript and have run into some problems while working with arrays.
In python, when I create an array and use for x in y I get this:
myarray = [5,4,3,2,1]
for x in myarray:
print x
and I get the expected output of:
5
4
3
..n
But my problem is that when using Javascript I get a different and completely unexpected (to me) result:
var world = [5,4,3,2,1]
for (var num in world) {
alert(num);
}
and I get the result:
0
1
2
..n
How can I get JavaScript to output num as the value in the array like python and why is this happening?
JavaScript and Python are different, and you do things in different ways between them.
In JavaScript, you really should (almost) always iterate over an array with a numeric index:
for (var i = 0; i < array.length; ++i)
alert(array[i]);
The "for ... in" construct in JavaScript gives you the keys of the object, not the values. It's tricky to use on an array because it operates on the array as an object, treating it no differently than any other sort of object. Thus, if the array object has additional properties — which is completely "legal" and not uncommon — your loop will pick those up in addition to the indexes of the "normal" array contents.
The variable num contains the array item's index, not the value. So you'd want:
alert(world[num])
to retrieve the value
The for var in... loop in JavaScript puts the keys in the variable instead of the actual value. So when using for var ... you should do something like this:
var world = [5, 4, 3, 2, 1];
for ( var key in world ) {
var value = world[key];
alert(key + " = " + value);
}
And note that this way of looping is best used when you're using objects instead of arrays. For arrays use the common:
for ( var i = 0, j = arr.length; i < j; i++ ) { ... }
Or if you're targeting modern browser you can use the forEach-method of arrays:
var arr = [1, 2, 3];
arr.forEach(function(num) {
alert(num);
});
The for...in loop loops over all key elements; not the values.
I would recommend you to use
for(var i=0; i<arr.length; i++){
alert(arr[i]);
}
When you use the in operator num becomes a key. So simply use this key to get a value out of the array.
var world = [5,4,3,2,1]
for (var num in world) {
alert(world[num]);
}
try this.
var world = [5,4,3,2,1]
for(var i=0;i<world.length;i++){
alert(world[i])
}
Because javascript in your case is printing the index of the element, not the value.
the result you got is just element index,if you want to get element value
your code should like this
var world = [5,4,3,2,1]
for (var num in world) {
alert(world[num]);
}
The for in iteration in JavaScript works only for the object data type. The way it works is that it lets you iterate over the attributes of an object. arrays are objects in JavaScript, but the for in only works on its attributes, not the array values.
For example you might define an array as such:
var arr = [1,2,3];
And you can assign attributes to this array, because it's actually an object:
arr.foo = "bar";
arr["1"] = 2;
Now when you use the for in iteration method you will be able to iterate over the attributes we just assigned above;
for(var i in arr) console.log(i);
To iterate over the actual array values you need to use the for(var i=0; i<arr.length; i++) construct.
Hope this helps.
In javascript it's advised to loop Arrays different from looping Objects. You are using an object loop, which may return unexpected result (for instance if the Array.prototype was extended with custom methods you would iterate those too, and it does't guarantee the order of the array is preserved). There are many ways to loop through an array, using it's index:
// regular
var arr = [1,2,3,4,5]
,i
;
for (i=0;i<arr.length;i++) {
console.log(arr[i]);
}
// using while
var arr = [1,2,3,4,5]
,i = 0
;
while ((i = i + 1)<arr.length) {
console.log(arr[i]);
}
// using while reversed
var arr = [1,2,3,4,5]
,i = arr.length
;
while ((i = i - 1) > -1) {
console.log(arr[i]);
}
Note: Why not use i++ or i--? To avoid confusion, index out of range-errors and to satisfy JSLint

Categories