Copying an array to a variable whilst excluding items - Performance - javascript

I have this array right here -
var children = [Group, Path,Path, CompoundPath,Path];
I would like to copy the array into a variable, which I do like this
var selectionItems = children.slice();
Now I would like when copying the array into the variable, to keep in selectionItems only the items that are Path's.
I have tried the splice() method but I think it messes up the indices of the copied array which is something I would prefer not to happen. I also have no idea how to exclude anything else other than Path in the new copy of the array.
As always any help would be appreciated.

You can use .filter:
var selectionItems = children.filter(function (el) { return el instanceof Path; });

Related

add and remove specific array elements using array.splice()

Is it possible to add to a specific part of an array, and then deleting a specific part of the array, in this case the end value using arr.splice()?
i currently do this like so:
var arr = [1,2,3,4,5,6,7,8,9];
arr.splice(0,0,"test");
which should return:
"test",1,2,3,4,5,6,7,8,9
i then do:
arr.pop();
which should return:
"test",1,2,3,4,5,6,7,8
I was wondering if it's possible to do this via the arr.splice() method or if there is any cleaner method to do the same, as potentially i'll be doing this a few times, so i would end up with something like:
arr.splice(0,0,"test");
arr.pop();
arr.splice(1,0,"test2");
arr.pop();
looking at the array.splice documentation it suggests i can only delete the element in the position i'm putting the new element into, not a different one.
In answer to my original question as confirmed in the comments. It is not possible to provide a separate index to insert and another to remove in an array using the splice method or potentially any other single statement in javascript. The best approach to try to achieve this in a single statement if i really needed it would be to create your own function, which really seems counter productive for the most part.
You can use Array.from() to set the .length and values of specific indexes of an array in a single call
var arr = [1,2,3,4,5,6,7,8,9];
arr = Array.from({length:arr.length - 1, ...arr, 0:"test"});
console.log(arr);
To achieve the pattern described at Question you can alternatively use a loop and Object.assign()
var arr = [1,2,3,4,5,6,7,8,9];
var n = 0;
var prop = "test";
while (arr.length > 1) {
Object.assign(arr, {length:arr.length -1,...arr, [n]:!n ? prop : prop+n});
++n;
console.log(arr);
}

Javascript: how do I copy the value of a single element from an array into another array at the same position?

If I want to clone an array, I can use the slice() function, but what if I want to "clone" a single element? I want to do something like this:
array1[i] = array2[i];
but I want to copy the value, not the reference.
How can I do this? Also, will the solution work for associative arrays too? For example:
array1["one"] = array2["one"];
Thank you in advance.
You could use Object.assign and Array.splice
var cloneItem = Object.assign({}, array1[i]);
array2.splice(i, 0, cloneItem);
EDIT
The previous adds a clone item in the position, pushing the rest of the elements to the right. If you simply want to replace just do
array2[i] = Object.assign({}, array1[i]);
You can do this:
array1[i] = Object.assign({}, array2[i]);
But it doesn't work if there are primitives an array.
Also you can use slice method like you wrote:
array1[i] = array2.slice(i, 1);
Cloning an array properly (without leaving any references in the nested structure) is not that simple. You need a tool for that. Unfortunately it is not a part of standard array methods. You have to develop it yourself. Such as
Array.prototype.clone = function(){
return this.map(e => Array.isArray(e) ? e.clone() : e);
};
Once you have this tool at hand you can clone the array first and then assign whatever item of the clone array you wish; such as array1[i] = array2.clone()[i];

jquery exclude array elements

I have an array of elements which I want to maintain efficiently, adding and removing arrays of elements over time.
var myElements = $('.initial');
jquery's merge() seems perfect for adding items as it doesn't create a new array and just adds to the existing one:
$.merge(myElements, $('.to-add'));
Is there an equivalent for removing, that also modifies the array in-place? Something like:
$.exclude(myElements, $('.to-remove'));
I do actually have arrays of DOM elements, and the selectors are just used as examples.
Assuming that you're after the relative complement of b in a.
And you don't want to create additional objects while process.
The function is for both plain Array and jQuery set.
(thus used $.each, $.inArray instead of Array.prototype.forEach Array.prototype.indexOf)
I wrote a function that fits your requirement.
$.exclude = function(a,b) {
var idx;
$.each(b, function(i, val) {
while((idx = $.inArray(val, a)) !== -1) {
a.splice(idx, 1);
}
})
return a;
}
test this code here
https://jsfiddle.net/happyhj/uwd4L1dm/8/
and you can use like this.
$.exclude(myElements, $('.to-remove'));
use jquery not method,
var filtered = $(myElements).not($('.to-remove'));
You can use delete to remove an element from an array and then use $.grep to remove the empty space.
//[0] since $("#id") will be a jquery Object
//[0] will return the particular DOM element
var orgArray = [$("#merge1")[0],$("#merge2")[0],$("#merge3")[0]];
var secArray = [$("#merge4")[0],$("#merge5")[0]]
// Will merge other two values;
// jQuery merge will merge contents of
//two array into first array
var merArray = $.merge(secArray, orgArray);
// Want to remove $("#merge2");
var getIndex = merArray.indexOf($("#merge2")[0]);
if(getIndex >-1){
delete merArray[getIndex]
}
// length before filtering
$("#l1").text(merArray.length);
//Now will remove Empty Space
merArray = $.grep(merArray,function(n){
return n==0 || n
});
$("#l2").text(merArray.length);
JSFIDDLE
You are using methods that are meant for array literals. jQuery already has method add() which will return a modified jQuery object that includes the elements matching the selector
var myElements = $('.initial');
var newCollection = myElements.add('.to-add');
newCollection.not('.to-remove').doSomething();
Don't think of jQuery objects as arrays although they are array like.
Reference add()
It's not clear what your overall objective really is but most likely you can manage it with any number of filtering methods that already exist within the api

How Array work (Javascript)?

I have a array is product
product[1][...]
product[2][...]
...
And I have a other array is hold.
My command:
hold['product'] = product;
for(i in product){
delete product[i];
}
for(i in hold['product']){
alert(i);
}
And Nothing happen. hold array doesn't have any element when I delete element of product array?
That is expected behavior. Complex types such as arrays are passed by reference in JavaScript. So when you assign an array to another variable, you are really assigning the reference. In order to avoid it, you should assign a copy of the original.
Try:
hold['product'] = product.slice(0);
try this one
var hold['product'] = product.slice();
It will create new copy of array on heap memory.So both array have their own copy
for more please check this one slice

Copying an array of objects into another array in javascript (Deep Copy)

Copying an array of objects into another array in javascript using slice(0) and concat() doesnt work.
I have tried the following to test if i get the expected behaviour of deep copy using this. But the original array is also getting modified after i make changes in the copied array.
var tags = [];
for(var i=0; i<3; i++) {
tags.push({
sortOrder: i,
type: 'miss'
})
}
for(var tag in tags) {
if(tags[tag].sortOrder == 1) {
tags[tag].type = 'done'
}
}
console.dir(tags)
var copy = tags.slice(0)
console.dir(copy)
copy[0].type = 'test'
console.dir(tags)
var another = tags.concat()
another[0].type = 'miss'
console.dir(tags)
How can i do a deep copy of a array into another, so that the original array is not modified if i make a change in copy array.
Try
var copy = JSON.parse(JSON.stringify(tags));
Try the following
// Deep copy
var newArray = jQuery.extend(true, [], oldArray);
For more details check this question out What is the most efficient way to deep clone an object in JavaScript?
As mentioned Here .slice(0) will be effective in cloning the array with primitive type elements. However in your example tags array contains anonymous objects. Hence any changes to these objects in cloned array are reflected in tags array.
#dangh's reply above derefences these element objects and create new ones.
Here is another thread addressing similar situation
A nice way to clone an array of objects with ES6 is to use spread syntax:
const clonedArray = [...oldArray];
MDN
Easiest and the optimistic way of doing this in one single line is using Underscore/Lodash
let a = _.map(b, _.clone)
You just need to use the '...' notation.
// THE FOLLOWING LINE COPIES all elements of 'tags' INTO 'copy'
var copy = [...tags]
When you have an array say x, [...x] creates a new array with all the values of x. Be careful because this notation works slightly differently on objects. It splits the objects into all of its key, value pairs. So if you want to pass all the key value pairs of an object into a function you just need to pass function({...obj})
Same issue happen to me. I have data from service and save to another variable. When ever I update my array the copied array also updated. old code is like below
//$scope.MyData get from service
$scope.MyDataOriginal = $scope.MyData;
So when ever I change $scope.MyData also change $scope.MyDataOriginal.
I found a solution that angular.copy right code as below
$scope.MyDataOriginal = angular.copy($scope.MyData);
I know that this is a bit older post but I had the good fortune to have found a decent way to deep copy arrays, even those containing arrays, and objects, and even objects containing arrays are copied... I only can see one issue with this code is if you don't have enough memory I can see this choking on very large arrays of arrays and objects... But for the most part it should work. The reason that I am posting this here is that it accomplishes the OP request to copy array of objects by value and not by reference... so now with the code (the checks are from SO, the main copy function I wrote myself, not that some one else probably hasn't written before, I am just not aware of them)::
var isArray = function(a){return (!!a) && (a.constructor===Array);}
var isObject = function(a){return (!!a) && (a.constructor===Object);}
Array.prototype.copy = function(){
var newvals=[],
self=this;
for(var i = 0;i < self.length;i++){
var e=self[i];
if(isObject(e)){
var tmp={},
oKeys=Object.keys(e);
for(var x = 0;x < oKeys.length;x++){
var oks=oKeys[x];
if(isArray(e[oks])){
tmp[oks]=e[oks].copy();
} else {
tmp[oks]=e[oks];
}
}
newvals.push(tmp);
} else {
if(isArray(e)){
newvals.push(e.copy());
} else {
newvals.push(e);
}
}
}
return newvals;
}
This function (Array.prototype.copy) uses recursion to recall it self when an object or array is called returning the values as needed. The process is decently speedy, and does exactly what you would want it to do, it does a deep copy of an array, by value... Tested in chrome, and IE11 and it works in these two browsers.
The way to deeply copy an array in JavaScript with JSON.parse:
let orginalArray=
[
{firstName:"Choton", lastName:"Mohammad", age:26},
{firstName:"Mohammad", lastName:"Ishaque", age:26}
];
let copyArray = JSON.parse(JSON.stringify(orginalArray));
copyArray[0].age=27;
console.log("copyArray",copyArray);
console.log("orginalArray",orginalArray);
For this i use the new ECMAScript 6 Object.assign method :
let oldObject = [1,3,5,"test"];
let newObject = Object.assign({}, oldObject)
the first argument of this method is the array to be updated,
we pass an empty object because we want to have a completely new object,
also you can add other objects to be copied too :
let newObject = Object.assign({}, oldObject, o2, o3, ...)

Categories