var arr1 = [1,2,3,4,5];
var arr2 = ["a","b","c","d","e"];
Let's assume that I want to create a list like
1 a
2 b
3 c
4 d
5 e
by using template literal.
let x;
x = document.createElement('li');
x.innerHTML += `<span>${<arr1 index>}</span> <span>${<arr2 index>}</span>`
How can I do that ? Can we use forEach for two arrays in same time ?
This would be more like flatten(zip(arr1, arr2)). There is no built-in zip though you can very easily make it and you can see Array.flat here: MDN: Array.flat.
const arr1 = [1, 2, 3, 4, 5];
const arr2 = ["a", "b", "c", "d", "e"];
const flatten = arr => arr.flat();
const zip = (a, b) => a.map((e, idx) => [e, b[idx]]);
const arr3 = flatten(zip(arr1, arr2));
console.log(arr3);
The answer is "kind of." What you can do is loop through one array with a forEach method, and use the optional argument index to get the value of the second array as well. Something like this:
var arr1 = [1,2,3,4,5];
var arr2 = ["a","b","c","d","e"];
arr1.forEach((value, index) => {
console.log(value);
console.log(arr2[index])
})
But if the data in the two arrays are at all related, you'd want to put the data in the same object, like this:
var arr = [
{
num: 1,
letter: "a"
},
{
num: 2,
letter: "b"
},
{
num: 3,
letter: "c"
}
];
arr.forEach(value => {
console.log(value.num);
console.log(value.letter);
})
Or you would want to use a regular for loop
You could simply use a for() loop instead:
const max = Math.max(arrA.length, arrB.length)
for (let i = 0; i < max; i++) {
const objA = arrA[i],
objB = arrB[i]
if ('undefined' !== typeof objA) {
console.log({ objA })
}
if ('undefined' !== typeof objB) {
console.log({ objB })
}
}
There is no real magic here. You use an index variable, and let it increment:
var arr1 = [1,2,3,4,5];
var arr2 = ["a","b","c","d","e"];
let ul = document.querySelector("ul");
for (let i = 0; i < arr1.length; i++) {
let li = document.createElement('li');
for (let val of [arr1[i], arr2[i]]) {
let span = document.createElement('span');
span.textContent = val;
li.appendChild(span);
}
ul.appendChild(li);
}
<ul></ul>
There are of course other ways to loop, like with forEach, but it comes down to the same principle.
BTW, don't use string literals (template literals) for combining HTML with content, as you might have < or & characters in the content, which really should be escaped. In some cases, not escaping those may lead to unexpected side effects. By creating the elements with createElement and assigning content to their textContent or innerText properties, you avoid those potential issues. Some libraries make it possible to do this with less code, in a more functional way.
As to the initial data: in object oriented languages, like JavaScript, it is better practice to put related values together in one object. In the example, 1 and "a" apparently have a connection, so -- if possible -- you should define the initial data structure as something like this:
var data = [
{ value: 1, name: "a" },
{ value: 2, name: "b" },
{ value: 3, name: "c" },
{ value: 4, name: "d" },
{ value: 5, name: "e" }
];
So I hacked this code from somewhere else, but have an object variable to store x,y values in an array every time a hex is clicked, defined with two functions, one to add an element and one to remove the last element
var objMoves = {
length: 0,
addElem: function addElem(elem) {
// obj.length is automatically incremented
// every time an element is added.
[].push.call(this, elem);
},
removeElem: function removeElem(last) {
// this removes the last item in the array
[].splice.call(this,last, 1);
}
};
I call it like this:
objMoves.addElem({ x: hexX, y: hexY });
Result if I dump the objMoves into the console log is "{"0":{"x":2,"y":1},"length":1}"
However, what I really want is something like
objMoves.addElem({ x: hexX, y: hexY },stackID:"abcdef");
So the result would be something like
{stackId:"abcdef",moves:[{"x":2,"y":1},{"x":3,"y":4}]}
{stackId:"xyz",moves:[{"x":5,"y":2},{"x":6,"y":2},{"x":7,"y":2}]}
etc, where the inner array gets added to for a given stackID. I think I need to nest the objects?
push() is for arrays, not objects, so use the right data structure.
var objMoves = [];
// ...
data[0] = { "": "", "": "" };
data[1] = { ....};
// ...
var tempData = [];
for ( var index=0; index<data.length; index++ ) {
if ( data[index].objMoves ) {
tempData.push( data );
}
}
data = tempData;
or deal with it like it is an object. while Objects does not support push property, you can save it as well using the index as key.
It sounds like what you're looking for is something like this:
var objMoves = {
addElem: function(id, elem) {
var obj = this[id] || {
stackId: id,
moves: []
};
obj.moves.push(elem);
this[id] = obj;
},
removeElem: function(id, last) {
this[id].moves.splice(last, 1);
}
}
objMoves.addElem("abcdef", {x: 123, y: 456});
objMoves.addElem("xyz", {x: 1, y: 2});
objMoves.addElem("abcdef", {x: 100, y: 50});
console.log(objMoves);
The functions take a stack ID as a parameter, so they can use that as a key into the object to find the sub-object with that ID. The moves are stored in an array in that sub-object.
I was a little bit fascinated from the code, that you have taken from the MDN JavaScript reference site. It shows us how we could use an object as an array. And so I wrote some functions to do it.
Solution with all, what you need:
var objMoves =
{
// objMoves.length is automatically incremented every time an element is added
length: 0,
//add an object to new(with stackId) or given(by stackId) array element
addElem: function(object, stackId)
{
var index = this.getElemIndex(stackId);
if(index > -1)
this[index].moves.push(object);
else
[].push.call(this, {stackId: stackId, moves: [object]})
},
//remove the array element on lastElemIndex
removeElem: function(lastElemIndex)
{
[].splice.call(this, lastElemIndex, 1)
},
//remove the object on lastElemIndex from the array element with stackId
removeMovesElem: function(stackId, lastElemIndex)
{
var index = this.getElemIndex(stackId);
if(index > -1)
this[index].moves.splice(lastElemIndex, 1)
},
//get the array element index by stackId
getElemIndex: function(stackId)
{
for(var i = this.length; i--;)
if(this[i].stackId == stackId)
return i
return -1
}
};
//we check functions:
objMoves.addElem({x: 2, y: 1}, 'abcdef');
objMoves.addElem({x: 3, y: 4}, 'abcdef');
objMoves.addElem({x: 5, y: 2}, 'xyz');
objMoves.addElem({x: 6, y: 2}, 'xyz');
objMoves.addElem({x: 7, y: 2}, 'xyz');
console.log(JSON.stringify(objMoves, null, '\t'));
console.log('===========================');
var index = objMoves.getElemIndex('abcdef');
objMoves.removeElem(index);
console.log(JSON.stringify(objMoves, null, '\t'));
console.log('===========================');
objMoves.removeMovesElem('xyz', 1);
console.log(JSON.stringify(objMoves, null, '\t'));
Say I have the array [1,2,3,5,2,1,4]. How do I get make JS return [3,4,5]?
I've looked at other questions here but they're all about delete the copies of a number which appears more than once, not both the original and the copies.
Thanks!
Use Array#filter method twice.
var data = [1, 2, 3, 5, 2, 1, 4];
// iterate over elements and filter
var res = data.filter(function(v) {
// get the count of the current element in array
// and filter based on the count
return data.filter(function(v1) {
// compare with current element
return v1 == v;
// check length
}).length == 1;
});
console.log(res);
Or another way using Array#indexOf and Array#lastIndexOf methods.
var data = [1, 2, 3, 5, 2, 1, 4];
// iterate over the array element and filter out
var res = data.filter(function(v) {
// filter out only elements where both last
// index and first index are the same.
return data.indexOf(v) == data.lastIndexOf(v);
});
console.log(res);
You can also use .slice().sort()
var x = [1,2,3,5,2,1,4];
var y = x.slice().sort(); // the value of Y is sorted value X
var newArr = []; // define new Array
for(var i = 0; i<y.length; i++){ // Loop through array y
if(y[i] != y[i+1]){ //check if value is single
newArr.push(y[i]); // then push it to new Array
}else{
i++; // else skip to next value which is same as y[i]
}
}
console.log(newArr);
If you check newArr it has value of:
[3, 4, 5]
var arr = [1,2,3,5,2,1,4]
var sorted_arr = arr.slice().sort(); // You can define the comparing function here.
var nonduplicates = [];
var duplicates=[];
for (var i = 0; i < arr.length; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
duplicates.push(sorted_arr[i]);
}else{
if(!duplicates.includes(sorted_arr[i])){
nonduplicates.push(sorted_arr[i]);
}
}
}
alert("Non duplicate elements >>"+ nonduplicates);
alert("Duplicate elements >>"+duplicates);
I think there could exists option with Map.
function unique(array) {
// code goes here
const myMap = new Map();
for (const el of array) {
// save elements of array that came only once in the same order
!myMap.has(el) ? myMap.set(el, 1) : myMap.delete(el);
}
return [...myMap.keys()];
}
const array = [1,2,3,5,2,1,4];
//[11, 23, 321, 300, 50, 23, 100,89,300];
console.log(unique(array));
I am looping through an object and then upon each object I am comparing it to the items in my array in hopes to then push the objects that are not the same into my ItemsNotInObject array. Hopefully someone can shine some light on this for me. Thank you in advance.
var obj = {a:1, a:2, a:3};
var array = [1, 4, 2, 5, 6];
var ItemsNotInObject = [];
for (var prop in obj) {
for(var i = 0, al = array.length; i < al; i++){
if( obj[prop].a !== array[i] ){
ItemsNotInObject.push(array[i]);
}
}
}
console.log(ItemsNotInObject);
//output of array: 1 , 4 , 2 , 5, 6
//output desired is: 4 , 5 , 6
Your object has duplicate keys. This is not a valid JSON object. Make them unique
Do not access the object value like obj[prop].a, obj[prop] is a
Clone the original array.
Use indexOf() to check if the array contains the object property or not.
If it does, remove it from the cloned array.
var obj = {
a: 1,
b: 2,
c: 3
};
var array = [1, 4, 2, 5, 6];
var ItemsNotInObject = array.slice(); //clone the array
for (var prop in obj) {
if (array.indexOf(obj[prop]) != -1) {
for (var i = 0; i < ItemsNotInObject.length; i++) {
if (ItemsNotInObject[i] == obj[prop]) {
ItemsNotInObject.splice(i, 1); //now simply remove it because it exists
}
}
}
}
console.log(ItemsNotInObject);
If you can make your obj variable an array, you can do it this way;
var obj = [1, 2, 3];
var array = [1, 4, 2, 5, 6];
var ItemsNotInObject = [];
for(i in array){
if( obj.indexOf(array[i]) < 0) ItemsNotInObject.push(array[i]);
}
console.log(ItemsNotInObject);
if the obj variable needs to be json object please provide the proper form of it so i can change the code according to that.
I have two arrays. The first array contains some values while the second array contains indices of the values which should be removed from the first array. For example:
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
I want to remove the values present at indices 0,2,4 from valuesArr. I thought the native splice method might help so I came up with:
$.each(removeValFromIndex,function(index,value){
valuesArr.splice(value,1);
});
But it didn't work because after each splice, the indices of the values in valuesArr were different. I could solve this problem by using a temporary array and copying all values to the second array, but I was wondering if there are any native methods to which we can pass multiple indices at which to remove values from an array.
I would prefer a jQuery solution. (Not sure if I can use grep here)
There's always the plain old for loop:
var valuesArr = ["v1","v2","v3","v4","v5"],
removeValFromIndex = [0,2,4];
for (var i = removeValFromIndex.length -1; i >= 0; i--)
valuesArr.splice(removeValFromIndex[i],1);
Go through removeValFromIndex in reverse order and you can .splice() without messing up the indexes of the yet-to-be-removed items.
Note in the above I've used the array-literal syntax with square brackets to declare the two arrays. This is the recommended syntax because new Array() use is potentially confusing given that it responds differently depending on how many parameters you pass in.
EDIT: Just saw your comment on another answer about the array of indexes not necessarily being in any particular order. If that's the case just sort it into descending order before you start:
removeValFromIndex.sort(function(a,b){ return b - a; });
And follow that with whatever looping / $.each() / etc. method you like.
I suggest you use Array.prototype.filter
var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = [0, 2, 4];
valuesArr = valuesArr.filter(function(value, index) {
return removeValFrom.indexOf(index) == -1;
})
Here is one that I use when not going with lodash/underscore:
while(IndexesToBeRemoved.length) {
elements.splice(IndexesToBeRemoved.pop(), 1);
}
Not in-place but can be done using grep and inArray functions of jQuery.
var arr = $.grep(valuesArr, function(n, i) {
return $.inArray(i, removeValFromIndex) ==-1;
});
alert(arr);//arr contains V2, V4
check this fiddle.
A simple and efficient (linear complexity) solution using filter and Set:
const valuesArr = ['v1', 'v2', 'v3', 'v4', 'v5'];
const removeValFromIndex = [0, 2, 4];
const indexSet = new Set(removeValFromIndex);
const arrayWithValuesRemoved = valuesArr.filter((value, i) => !indexSet.has(i));
console.log(arrayWithValuesRemoved);
The great advantage of that implementation is that the Set lookup operation (has function) takes a constant time, being faster than nevace's answer, for example.
This works well for me and work when deleting from an array of objects too:
var array = [
{ id: 1, name: 'bob', faveColor: 'blue' },
{ id: 2, name: 'jane', faveColor: 'red' },
{ id: 3, name: 'sam', faveColor: 'blue' }
];
// remove people that like blue
array.filter(x => x.faveColor === 'blue').forEach(x => array.splice(array.indexOf(x), 1));
There might be a shorter more effecient way to write this but this does work.
It feels necessary to post an answer with O(n) time :). The problem with the splice solution is that due to the underlying implementation of array being literally an array, each splice call will take O(n) time. This is most pronounced when we setup an example to exploit this behavior:
var n = 100
var xs = []
for(var i=0; i<n;i++)
xs.push(i)
var is = []
for(var i=n/2-1; i>=0;i--)
is.push(i)
This removes elements starting from the middle to the start, hence each remove forces the js engine to copy n/2 elements, we have (n/2)^2 copy operations in total which is quadratic.
The splice solution (assuming is is already sorted in decreasing order to get rid of overheads) goes like this:
for(var i=0; i<is.length; i++)
xs.splice(is[i], 1)
However, it is not hard to implement a linear time solution, by re-constructing the array from scratch, using a mask to see if we copy elements or not (sort will push this to O(n)log(n)). The following is such an implementation (not that mask is boolean inverted for speed):
var mask = new Array(xs.length)
for(var i=is.length - 1; i>=0; i--)
mask[is[i]] = true
var offset = 0
for(var i=0; i<xs.length; i++){
if(mask[i] === undefined){
xs[offset] = xs[i]
offset++
}
}
xs.length = offset
I ran this on jsperf.com and for even n=100 the splice method is a full 90% slower. For larger n this difference will be much greater.
I find this the most elegant solution:
const oldArray = [1, 2, 3, 4, 5]
const removeItems = [1, 3, 5]
const newArray = oldArray.filter((value) => {
return !removeItems.includes(value)
})
console.log(newArray)
output:
[2, 4]
or even shorter:
const newArray = oldArray.filter(v => !removeItems.includes(v))
function filtermethod(element, index, array) {
return removeValFromIndex.find(index)
}
var result = valuesArr.filter(filtermethod);
MDN reference is here
In pure JS you can loop through the array backwards, so splice() will not mess up indices of the elements next in the loop:
for (var i = arr.length - 1; i >= 0; i--) {
if ( yuck(arr[i]) ) {
arr.splice(i, 1);
}
}
A simple solution using ES5. This seems more appropriate for most applications nowadays, since many do no longer want to rely on jQuery etc.
When the indexes to be removed are sorted in ascending order:
var valuesArr = ["v1", "v2", "v3", "v4", "v5"];
var removeValFromIndex = [0, 2, 4]; // ascending
removeValFromIndex.reverse().forEach(function(index) {
valuesArr.splice(index, 1);
});
When the indexes to be removed are not sorted:
var valuesArr = ["v1", "v2", "v3", "v4", "v5"];
var removeValFromIndex = [2, 4, 0]; // unsorted
removeValFromIndex.sort(function(a, b) { return b - a; }).forEach(function(index) {
valuesArr.splice(index, 1);
});
Quick ES6 one liner:
const valuesArr = new Array("v1","v2","v3","v4","v5");
const removeValFromIndex = new Array(0,2,4);
const arrayWithValuesRemoved = valuesArr.filter((value, i) => removeValFromIndex.includes(i))
If you are using underscore.js, you can use _.filter() to solve your problem.
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
var filteredArr = _.filter(valuesArr, function(item, index){
return !_.contains(removeValFromIndex, index);
});
Additionally, if you are trying to remove items using a list of items instead of indexes, you can simply use _.without(), like so:
var valuesArr = new Array("v1","v2","v3","v4","v5");
var filteredArr = _.without(valuesArr, "V1", "V3");
Now filteredArr should be ["V2", "V4", "V5"]
You can correct your code by replacing removeValFromIndex with removeValFromIndex.reverse(). If that array is not guaranteed to use ascending order, you can instead use removeValFromIndex.sort(function(a, b) { return b - a }).
Here's one possibility:
valuesArr = removeValFromIndex.reduceRight(function (arr, it) {
arr.splice(it, 1);
return arr;
}, valuesArr.sort(function (a, b) { return b - a }));
Example on jsFiddle
MDN on Array.prototype.reduceRight
filter + indexOf (IE9+):
function removeMany(array, indexes) {
return array.filter(function(_, idx) {
return indexes.indexOf(idx) === -1;
});
});
Or with ES6 filter + find (Edge+):
function removeMany(array, indexes = []) {
return array.filter((_, idx) => indexes.indexOf(idx) === -1)
}
Here's a quickie.
function removeFromArray(arr, toRemove){
return arr.filter(item => toRemove.indexOf(item) === -1)
}
const arr1 = [1, 2, 3, 4, 5, 6, 7]
const arr2 = removeFromArray(arr1, [2, 4, 6]) // [1,3,5,7]
Try this
var valuesArr = new Array("v1", "v2", "v3", "v4", "v5");
console.info("Before valuesArr = " + valuesArr);
var removeValFromIndex = new Array(0, 2, 4);
valuesArr = valuesArr.filter((val, index) => {
return !removeValFromIndex.includes(index);
})
console.info("After valuesArr = " + valuesArr);
Sounds like Apply could be what you are looking for.
maybe something like this would work?
Array.prototype.splice.apply(valuesArray, removeValFromIndexes );
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
console.log(valuesArr)
let arr2 = [];
for (let i = 0; i < valuesArr.length; i++){
if ( //could also just imput this below instead of index value
valuesArr[i] !== valuesArr[0] && // "v1" <--
valuesArr[i] !== valuesArr[2] && // "v3" <--
valuesArr[i] !== valuesArr[4] // "v5" <--
){
arr2.push(valuesArr[i]);
}
}
console.log(arr2);
This works. However, you would make a new array in the process. Not sure if thats would you want or not, but technically it would be an array containing only the values you wanted.
You can try Lodash js library functions (_.forEach(), _.remove()). I was using this technique to remove multiple rows from the table.
let valuesArr = [
{id: 1, name: "dog"},
{id: 2, name: "cat"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
{id: 5, name: "pig"},
];
let removeValFromIndex = [
{id: 2, name: "cat"},
{id: 5, name: "pig"},
];
_.forEach(removeValFromIndex, (indi) => {
_.remove(valuesArr, (item) => {
return item.id === indi.id;
});
})
console.log(valuesArr)
/*[
{id: 1, name: "dog"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
];*/
Don't forget to clone (_.clone(valuesArr) or [...valuesArr]) before mutate your array
You could try and use delete array[index] This won't completely remove the element but rather sets the value to undefined.
removeValFromIndex.forEach(function(toRemoveIndex){
valuesArr.splice(toRemoveIndex,1);
});
For Multiple items or unique item:
I suggest you use Array.prototype.filter
Don't ever use indexOf if you already know the index!:
var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = [0, 2, 4];
valuesArr = valuesArr.filter(function(value, index) {
return removeValFrom.indexOf(index) == -1;
}); // BIG O(N*m) where N is length of valuesArr and m is length removeValFrom
Do:
with Hashes... using Array.prototype.map
var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = {};
([0, 2, 4]).map(x=>removeValFrom[x]=1); //bild the hash.
valuesArr = valuesArr.filter(function(value, index) {
return removeValFrom[index] == 1;
}); // BIG O(N) where N is valuesArr;
You could construct a Set from the array and then create an array from the set.
const array = [1, 1, 2, 3, 5, 5, 1];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // Result: [1, 2, 3, 5]