Why doesn't Array.push.apply work? - javascript

As described here, a quick way to append array b to array a in javascript is a.push.apply(a, b).
You'll note that the object a is used twice. Really we just want the push function, and b.push.apply(a, b) accomplishes exactly the same thing -- the first argument of apply supplies the this for the applied function.
I thought it might make more sense to directly use the methods of the Array object: Array.push.apply(a, b). But this doesn't work!
I'm curious why not, and if there's a better way to accomplish my goal. (Applying the push function without needing to invoke a specific array twice.)

It's Array.prototype.push, not Array.push

You can also use [].push.apply(a, b) for shorter notation.

The current version of JS allows you to unpack an array into the arguments.
var a = [1, 2, 3, 4, 5,];
var b = [6, 7, 8, 9];
a.push(...b); //[1, 2, 3, 4, 5, 6, 7, 8, 9];

What is wrong with Array.prototype.concat?
var a = [1, 2, 3, 4, 5];
var b = [6, 7, 8, 9];
a = a.concat(b); // [1, 2, 3, 4, 5, 6, 7, 8, 9];

Related

Accessing and returning nested array value

I can't seem to figure this out. I just get an undefined return.
let test = [1, 2, 3, 4, [6, 7, 8]];
How do I return the index [2] of test[4]?
I'm not even sure I'm asking the question properly.
Basically, I want to interact with 8.
To maybe help you understand what is going on.
If you write
let test = [1, 2, 3, 4, [6, 7, 8]];
you create an array (which is more like a list if you compare it to other languages). Every entry has its own datatype. So in the example we have the first 4 elements which are just numbers and the fifth entry which is another Array.
With the [] operator we address certain elements inside the array. If we want the first entry we can use test[0] and should get back 1.
You now want to access an element in the array inside an array. So you first address the array in the array. test[4] this will give you back [6, 7, 8] and now you can do the same thing again and address this new array. You could write it this way
let test = [1, 2, 3, 4, [6, 7, 8]];
let innerArray = test[4];
let element = innerArray[2];
The example above is just to better understand what is going on. In practice you will just do test[4][2] and it will basically to the same as above.
Try this.
let test = [1, 2, 3, 4, [6, 7, 8]];
console.log(test[4][2])

Remove an item from an array by value, but leave the duplicates of that item

I have a very simple array like this:
array = [1, 1, 6, 7, 9, 6, 4, 5, 4];
I need to be able to remove a value, but I need to remove only one value if there's duplicate values. So if I remove the value 6, the array should become:
array = [1, 1, 7, 9, 6, 4, 5, 4];
The order of which one gets removed doesn't matter, so it could be the last no. 6 or the first no. 6. How can I do this?
Edit
I see there's a lot of confusion about why I need this, which results in incorrect answers. I'm making a Sudoku game and when a user inserts a number in a cell, the game has to check if the chosen number already occupies space in the same row or column. If so, the number of that specific row/column is added to this array. However, when a user fixes a mistake, the number of the row/column should be removed. A user can, however, make multiple mistakes in the same row or column, which is why I need to retain the duplicates in the array. Otherwise, users can make multiple mistakes in a row/column, and only fix one, and then the code will think there are no errors whatsoever anymore.
Hope this makes things more clear.
Try to get the index of your item with indexOf() and then call splice()
let array = [1, 1, 6, 7, 9, 6, 4, 5, 4];
let index = array.indexOf(6);
array.splice(index,1);
console.log(array);
var array=[1, 1, 6, 7, 9, 6, 4, 5, 4],
removeFirst=function(val,array){
array.splice(array.indexOf(val),1)
return array;
};
console.log(removeFirst(6,array));
You can use Array.prototype.findIndex to find the first index at which the element to be removed appears and then splice it.
Also you can create a hastable to ascertain that we remove only if a duplicate is availabe - see demo below:
var array = [1, 1, 6, 7, 9, 6, 4, 5, 4];
var hash = array.reduce(function(p,c){
p[c] = (p[c] || 0) + 1;
return p;
},{});
function remove(el) {
if(hash[el] < 2)
return;
array.splice(array.findIndex(function(e) {
return e == el;
}), 1);
}
remove(6);
remove(7);
console.log(array);
If order of removed element (not elements!) isn't important, you can use something like this:
array = [1, 1, 6, 7, 9, 6, 4, 5, 4];
function remove_if_dupe(elem, array) {
dupes=[];
for(i=0;i<array.length;i++) {
if(array[i] === elem) {
dupes.push(elem);
}
}
if(dupes.length>1) {
//is duplicated
array.splice(array.indexOf(elem), 1);
}
return array;
}
console.log(remove_if_dupe(6,array));
This should keep unique elements, hopefully.

initialize all the values in a javascript array to 0 without iteration

is there any way to make javascript array to initialize all the values to 0 without iteration like as shown below
var array = [1, 2, 3, 4, 5];
to
[0, 0, 0, 0, 0]
You could, in compliant browsers, use Array.prototype.fill():
var array = [1, 2, 3, 4, 5];
array.fill(0); // [0, 0, 0, 0, 0]
References:
Array.prototype.fill().
Array.apply(null, new Array(5)).map(Number.prototype.valueOf, 0))
Useful article Initializing arrays
Its a bit tricky. But it works
var array = [1, 2, 3, 4, 5];
array = JSON.parse(JSON.stringify(array).replace(/(\d+)/g,0)); // Returns [0,0,0,0,0]
i guess you don't need eval if you use JSON.parse() to build the empties and splice() to mutate the existing array instead of just making a new array full of zeros:
var r=[1, 2, 3, 4, 5];
[].splice.apply(r,
[0, r.length].concat(
JSON.parse("[0"+new Array(r.length).join(",0")+"]")
));
alert(r); // shows: "0,0,0,0,0"
Answers based on map()/fill() will not affect the orig array as desired, but those solutions could use splice like the above answer to do so, the only difference then is how one build the zero-filled array.
EDIT: kudos to Gilsha, i was working on an eval-based answer when you reminded me that JSON would be enough.

Nested array manipulation to look like a matrix

I'm retrieving some data and the data looks like this:
1, 2, 3, 4, 5
6, 7, 8, 9, 10
11, 12, 13, 14, 15
I want it to look like this
[
[[1],[2],[3],[4],[5]],
[[6],[7],[8],[9],[10]],
[[11],[12],[13],[14],[15]]
]
So that I may address the array like a matrix, data[0][1] would be "2".
Through this answer, it's almost there, but not quite. I'm having trouble getting to look like what I want.
How about this, assuming this accurately represents your input data:
var data = "1,2,3,4,5\n6,7,8,9,10\n11,12,13,14,15";
var matrix = data.split('\n').map(function(val) {
return val.split(',');
});
Note that your specified output is probably not what you meant. Each number should probably not be its own single-item array. Instead, the code above produces:
[
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 1]
]
Which means matrix[0][1] would return 2, as opposed to having to do matrix[0][1][0]
Edit: As noted in the comments, I've left it up to you to ensure this fits your browser-support needs. This also goes for every other line of JS you ever write...
NOTE - If you need to iterate through an array use a simple for, and not a for..in
for..in returns the items in no guaranteed order which is probably not what you want when working with an array
for..in returns not the just the array elements, but anything added to the Array prototype (meaning if you use a traditional for loop you can be completely confident the code will work regardless of what external libraries may be included on the page. No need to worry that some other coder has added properties/methods to Array.prototype)
If \n is the line separator and , is the item seperator within a line, you can use something like:
/* assuming data is already filled like:
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
*/
var arr = data.split("\n"), arr2 = [];
for(var i = 0; i < arr.length; i++) {
if(arr[i] != '') arr2.push(arr[i].split(','));
}
console.log(arr2);
/* arr2 will be like:
[
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
]
*/
var data = '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15'.split(',');
var matrixData = [];
while (data.length > 0) {
matrixData.push(data.splice(0, 5));
}
document.write(matrixData[0][1]);
Edit: If you get the data as a simple array of numbers

Retrieving a property of a JSON object by index?

Assuming this JSON object:
var obj = {
"set1": [1, 2, 3],
"set2": [4, 5, 6, 7, 8],
"set3": [9, 10, 11, 12]
};
The "set2" property may be retrieved like so:
obj["set2"]
Is there a way to retrieve the "set2" property by index? It is the second property of the JSON object. This does not work (of course):
obj[1]
So, let's say that I want to retrieve the second property of the JSON object, but I don't know its name - how would I do it then?
Update: Yes, I understand that objects are collections of unordered properties. But I don't think that the browsers mess with the "original" order defined by the JSON literal / string.
Objects in JavaScript are collections of unordered properties. Objects are hashtables.
If you want your properties to be in alphabetical order, one possible solution would be to create an index for your properties in a separate array. Just a few hours ago, I answered a question on Stack Overflow which you may want to check out:
Iterating over a JavaScript object in sort order based on particular key value of a child object
Here's a quick adaptation for your object1:
var obj = {
"set1": [1, 2, 3],
"set2": [4, 5, 6, 7, 8],
"set3": [9, 10, 11, 12]
};
var index = [];
// build the index
for (var x in obj) {
index.push(x);
}
// sort the index
index.sort(function (a, b) {
return a == b ? 0 : (a > b ? 1 : -1);
});
Then you would be able to do the following:
console.log(obj[index[1]]);
The answer I cited earlier proposes a reusable solution to iterate over such an object. That is unless you can change your JSON to as #Jacob Relkin suggested in the other answer, which could be easier.
1 You may want to use the hasOwnProperty() method to ensure that the properties belong to your object and are not inherited from Object.prototype.
I know this is an old question but I found a way to get the fields by index.
You can do it by using the Object.keys method.
When you call the Object.keys method it returns the keys in the order they were assigned (See the example below). I tested the method below in the following browsers:
Google Chrome version 43.0
Firefox version 33.1
Internet Explorer version 11
I also wrote a small extension to the object class so you can call the nth key of the object using getByIndex.
// Function to get the nth key from the object
Object.prototype.getByIndex = function(index) {
return this[Object.keys(this)[index]];
};
var obj1 = {
"set1": [1, 2, 3],
"set2": [4, 5, 6, 7, 8],
"set3": [9, 10, 11, 12]
};
var obj2 = {
"set2": [4, 5, 6, 7, 8],
"set1": [1, 2, 3],
"set3": [9, 10, 11, 12]
};
log('-- Obj1 --');
log(obj1);
log(Object.keys(obj1));
log(obj1.getByIndex(0));
log('-- Obj2 --');
log(obj2);
log(Object.keys(obj2));
log(obj2.getByIndex(0));
// Log function to make the snippet possible
function log(x) {
var d = document.createElement("div");
if (typeof x === "object") {
x = JSON.stringify(x, null, 4);
}
d.textContent= x;
document.body.appendChild(d);
}
No, there is no way to access the element by index in JavaScript objects.
One solution to this if you have access to the source of this JSON, would be to change each element to a JSON object and stick the key inside of that object like this:
var obj = [
{"key":"set1", "data":[1, 2, 3]},
{"key":"set2", "data":[4, 5, 6, 7, 8]},
{"key":"set3", "data":[9, 10, 11, 12]}
];
You would then be able to access the elements numerically:
for(var i = 0; i < obj.length; i++) {
var k = obj[i]['key'];
var data = obj[i]['data'];
//do something with k or data...
}
Simple solution, just one line..
var obj = {
"set1": [1, 2, 3],
"set2": [4, 5, 6, 7, 8],
"set3": [9, 10, 11, 12]
};
obj = Object.values(obj);
obj[1]....
Here you can access "set2" property following:
var obj = {
"set1": [1, 2, 3],
"set2": [4, 5, 6, 7, 8],
"set3": [9, 10, 11, 12]
};
var output = Object.keys(obj)[1];
Object.keys return all the keys of provided object as Array..
Jeroen Vervaeke's answer is modular and the works fine, but it can cause problems if it is using with jQuery or other libraries that count on "object-as-hashtables" feature of Javascript.
I modified it a little to make usable with these libs.
function getByIndex(obj, index) {
return obj[Object.keys(obj)[index]];
}
You could iterate over the object and assign properties to indexes, like this:
var lookup = [];
var i = 0;
for (var name in obj) {
if (obj.hasOwnProperty(name)) {
lookup[i] = obj[name];
i++;
}
}
lookup[2] ...
However, as the others have said, the keys are in principle unordered. If you have code which depends on the corder, consider it a hack. Make sure you have unit tests so that you will know when it breaks.
"""
This could be done in python as follows.
Form the command as a string and then execute
"""
context = {
"whoami": "abc",
"status": "0",
"curStep": 2,
"parentStepStatus": {
"step1":[{"stepStatus": 0, "stepLog": "f1.log"}],
"step2":[{"stepStatus": 0, "stepLog": "f2.log"}]
}
}
def punc():
i = 1
while (i < 10):
x = "print(" + "context" + "['parentStepStatus']" + "['%s']"%("step%s")%(i) + ")"
exec(x)
i+=1
punc()
There is no "second property" -- when you say var obj = { ... }, the properties inside the braces are unordered. Even a 'for' loop walking through them might return them in different orders on different JavaScript implementations.
it is quite simple...
var obj = {
"set1": [1, 2, 3],
"set2": [4, 5, 6, 7, 8],
"set3": [9, 10, 11, 12]
};
jQuery.each(obj, function(i, val) {
console.log(i); // "set1"
console.log(val); // [1, 2, 3]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
var obj = {
"set1": [
1,
2,
3
],
"set2": [
4,
5,
6,
7,
8
],
"set3": [
9,
10,
11,
12
]
};
var outputKeys = Object.keys(obj)[1];
var outputValues = Object.values(obj)[1];
//outputKeys would be "set2"`enter code here`
//outPutValues would be [4,5,6,7,8]
My solution:
Object.prototype.__index=function(index)
{var i=-1;
for (var key in this)
{if (this.hasOwnProperty(key) && typeof(this[key])!=='function')
{++i;
}
if (i>=index)
{return this[key];
}
}
return null;
}
aObj={'jack':3, 'peter':4, '5':'col', 'kk':function(){alert('hell');}, 'till':'ding'};
alert(aObj.__index(4));

Categories