Copy an array without linking to it [duplicate] - javascript

This question already has answers here:
Fastest way to duplicate an array in JavaScript - slice vs. 'for' loop
(25 answers)
Closed 6 years ago.
var ProtVar = function(arr){
this.gr1 = [];
this.gr2 = [];
this.arr = arr;
return this;
}
ProtVar.prototype.setArrs = function(){
this.gr1 = this.arr;
this.gr2 = this.arr;
return this;
}
ProtVar.prototype.shiftGr1 = function(){
this.gr1.shift();
return this;
}
ProtVar.prototype.showData = function(){
console.log("gr1 = ", this.gr1.length, this.gr1);
console.log("gr2 = ", this.gr2.length, this.gr2);
console.log("arr = ", this.arr.length, this.arr);
return this;
}
var protVar = new ProtVar([1,2,3,4]).setArrs().shiftGr1().showData();
How should I copy the array without linking to the same array?
I figured out how to do this with slice(0); see below.
ProtVar.prototype.setArrs = function(){
this.gr1 = this.arr.slice(0);
this.gr2 = this.arr.slice(0);
return this;
}
Is this the right way to do it?

There are at least 4 (!) principal ways to clone an array:
loop
constructor
slice / splice
concat
Please see this answer

Related

My function does not return the expected output and I can't figure out why; can somebody point out something I'm missing? [duplicate]

This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 3 years ago.
my function has to take 2 arrays and if one of the arrays is shorter than the other it needs to fill in the blanks with nulls.
so i could do this easier now that i think about it but i would really like to know what i have missed.
the specific part of my code is the nested forEach loops i cant understand that when i invoke my function like this
fillSquare([1,2,3],[1,2,3,4,5])
I get [[1,2,3,4,5],[1,2,3,4,5]] instead of [[1,2,3,null,null][1,2,3,4,5]]
const fillSquare = arr => {
const maxArrayLength = Math.max(
...arr.map(arr => {
return arr.length;
})
);
let arrayMatrix = new Array(arr.length).fill(
new Array(maxArrayLength).fill(null)
);
arr.forEach((arry, mainIndex) => {
arry.forEach((item, subIndex) => {
console.log(mainIndex, "<--main", "sub-->", subIndex, "=", item);
arrayMatrix[mainIndex][subIndex] = item;
});
});
console.log(arrayMatrix);
return arrayMatrix;
};
When debugging, it seems:
let arrayMatrix = new Array(arr.length).fill(
new Array(maxArrayLength).fill(null)
);
// arrayMatrix[1] == arrayMatrix[0] => true
is only creating 1 array instance. setting 1 value on one sets it on both.
heres how to fix your issue
let arrayMatrix = new Array(arr.length).fill(0).map( _ => new Array(maxArrayLength).fill(null));
this is my version - now immutable
function fillSquare(arr) {
let clone = [...arr]
let maxDepth = arr.reduce( (c, subarr) => c = Math.max(c, subarr.length), 0)
clone.forEach((subarr, index) => {
let len = clone[index].length;
clone[index].length = maxDepth;
clone[index].fill(null, len, maxDepth);
})
return clone;
}
the import notes are you can set the length and fill the gaps. Also check out reduce if you need.
const fillSquare = function(arr){
let minLengthArr = arr[0];
let maxLength = arr[1].length;
if(arr[1].length < arr[0].length){
minLengthArr= arr[1];
maxLength = arr[0].length;
}
let itemsToPush = maxLength - minLengthArr.length;
for(let i=0;i<itemsToPush;i++){
minLengthArr.push(null);
}
return arr;
}
var r = fillSquare([[1,2,3],[1,2,3,4,5]]);
console.log(r);

Create child objects from parent with same property values [duplicate]

This question already has answers here:
How to put items into grouped arrays where grouped by a particular key
(3 answers)
Closed 9 years ago.
I have a parent object. I want to create child objects from the parent with the same key value pair.
e.g.
parentJSON = {[name:"a1",address:"b1",comp:"c1"],
[name:"a2",address:"b2",comp:"c1"],
[name:"a3",address:"b3",comp:"c2"],
[name:"a4",address:"b4",comp:"c2"],
[name:"a5",address:"b5",comp:"c2"],
[name:"a6",address:"b6",comp:"c3"]}
Now I want to create child objects having same "comp" value.
e.g.
childJSON1 = {[name:"a1",address:"b1",comp:"c1"],
[name:"a2",address:"b2",comp:"c1"]}
childJSON2 = {[name:"a3",address:"b3",comp:"c2"],
[name:"a4",address:"b4",comp:"c2"],
[name:"a5",address:"b5",comp:"c2"]}
childJSON3 = {[name:"a6",address:"b6",comp:"c3"]}
This is what I tried to make it little bit (it will change the parent object with a key indicating number of repetition):
parentJSON = [1,2,3,3,4,4,4,5];
var i=0, x, count, item;
while(i < parentJSON.length) {
count = 1;
item = parentJSON[i];
x = i+1;
while(x < parentJSON.length &&
(x = parentJSON.indexOf(item, x)) != -1) {
count += 1;
parentJSON.splice(x,1);
}
parentJSON[i] = new Array(parentJSON[i],count);
++i;
}
console.log(parentJSON);`
first of all your json is in the incorrect format, it should look like this
[{name:"a1",address:"b1",comp:"c1"},
{name:"a2",address:"b2",comp:"c1"},
{name:"a3",address:"b3",comp:"c2"},
{name:"a4",address:"b4",comp:"c2"},
{name:"a5",address:"b5",comp:"c2"},
{name:"a6",address:"b6",comp:"c3"}]
An array of objects.
My attempt, also very readable.
var result = {};
$.each(parentJSON, function (i, item) {
if(!result[item.comp]) {
result[item.comp] = [];
}
(result[item.comp]).push(item);
});
alert(JSON.stringify(result))
JsFiddle
First of all your json is actually invalid. You may have an array of objects, but not object which contains an array like that. Also your arrays looks more like objects, because the syntax with the dots is used for objects. Here is how I guess should look like:
var parentJSON = [
[{name:"a1",address:"b1",comp:"c1"}],
[{name:"a2",address:"b2",comp:"c1"}],
[{name:"a3",address:"b3",comp:"c2"}],
[{name:"a4",address:"b4",comp:"c2"}],
[{name:"a5",address:"b5",comp:"c2"}],
[{name:"a6",address:"b6",comp:"c3"}]
];
var child1 = parentJSON.slice(0, 2);
var child2 = parentJSON.slice(2, 5);
And you may use the .slice method to get specific elements of the array.
So..you need to clone objects?
maybe tou can try sth like this:
var sergi= {
name: "sergi",
age: 33
};
var bill = (JSON.parse(JSON.stringify(sergi)));
bill.name = "Bill";
console.log(sergi);
console.log(bill);
parentJSON = function(){
return [
{name:"a1",address:"b1",comp:"c1"},
{name:"a2",address:"b2",comp:"c1"},
{name:"a3",address:"b3",comp:"c2"},
{name:"a4",address:"b4",comp:"c2"},
{name:"a5",address:"b5",comp:"c2"},
{name:"a6",address:"b6",comp:"c3"}
];
}
childJSON1 = new parentJSON().slice(0,2);
childJSON2 = new parentJSON().slice(2,5);
childJSON3 = new parentJSON().slice(5,6);
Try this:
DEMO
var data = [
[{name:"a1",address:"b1",comp:"c1"}],
[{name:"a2",address:"b2",comp:"c1"}],
[{name:"a3",address:"b3",comp:"c2"}],
[{name:"a4",address:"b4",comp:"c2"}],
[{name:"a5",address:"b5",comp:"c2"}],
[{name:"a6",address:"b6",comp:"c3"}]
];
var groups = {};
$.each(data, function(i, item) {
var comp = item.comp;
delete item.comp;
if(groups[comp]) {
groups[comp].push(item);
} else {
groups[comp] = [item];
}
});
var result = $.map(data, function(group, key) {
var obj = {};
obj[key] = group;
return obj;
});
alert(JSON.stringify(groups))

Creating arrays in javascript dynamically [duplicate]

This question already has answers here:
Alter and Assign Object Without Side Effects
(7 answers)
Closed 9 years ago.
I'm new in Phonegap app development.
I want to create an array of this type.
var myColumnDefs = [
{id:"id1", name:"name1"},
{id:"id2", name:"name2"},.... ] ;
Please help me how I can do this using javascript.
Because I have to insert data in this coming from webservices.
try this code..
var dataArray = [];
var length = yourjsonAray.length;
for (var i = 0; i < length; i++) {
var obj = {
id: yourjsonAray.keyId[i].id,
name: yourjsonAray.keyName[i].name
};
dataArray.push(obj);
}
Define an array (main array)-
var myColumnDefs = new Array();
and an object
var myObj = new Object();
then in your for loop, simply -
myObj.id = "ID1";
myObj.name = "Name1";
myColumnDefs.push(myObj);
OR, (better way)
function myObj(id, name)
{
this.name = name;
this.id = id;
}
myColumnDefs = new array();
myColumnDefs.push(new myObj("ID1", "Name 1"));
and so on ..

How to in JavaScript or ExtJS: obj['a.b.c'] = 123 => obj.a.b.c = 123? [duplicate]

This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 9 years ago.
I need to convert an object with cannonical properties into object with nested properties, splited by '.'
Example:
From:
obj['a.b.c'] = 123;
to:
obj.a.b.c = 123;
Any elegant solutions?
Or maybe there is a solution in ExtJS to make form.getValues() to return an array of fields grouped by names like fieldname[1] or fieldname.1?
Have a look at the private method in ClassManager "createNamespaces". It's essentially what you need to do, except root shouldn't default to global, it should default to your object:
function setValue(o, key, value) {
var root = o,
parts = key.split('.'),
ln = parts.length,
part, i;
for (i = 0; i < ln; i++) {
part = parts[i];
if (typeof part != 'string') {
root = part;
} else {
if (!root[part]) {
root[part] = (i === ln - 1) ? value : {};
}
root = root[part];
}
}
}
var o = {};
setValue(o, 'a.b.c', 123);
console.log(o.a.b.c);

How to create copy of an Array? [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
Closed 9 years ago.
I have this code:
const settings = {
notes: [new musicnote(480,400,"wav/1.wav","cyan",true)],
emiters: [new emiter(300,240), new emiter(340,240)]
}
var notes = [];
var emiters = [];
var LoadLevel = function (level) {
if(settings[level] !== undefined){
currentLevel = level;
notes = settings[level].notes;
emiters = settings[level].emiters;
}
}
And when I change emiters array in game (delete or add some) it does the same to the settings.emiter array. So my question is - how to pass a new array instead of a reference to array in settings object?
You can do that with Array.slice:
var original = [];
var copy = original.slice();
// to test:
copy.push("foo");
alert(original.length); // 0

Categories