Array and object copy in Javascript - javascript

I have the following data :
[
{"date":1900,"data":[
{"name":"Blackbird","value":0},
{"name":"Seagull","value":1},
{"name":"Sparrow","value":0}
]},
{"date":1910,"data":[
{"name":"Owl","value":1}
]},
{"date":1920,"data":[
{"name":"Eagle","value":0},
{"name":"Albatross","value":2}
]}
]
I need to make an incremental array of arrays from it. It should look something like this :
[
[
{"name":"Blackbird","value":0,"date":1900},
{"name":"Seagull","value":1,"date":1900},
{"name":"Sparrow","value":0,"date":1900}
],
[
{"name":"Blackbird","value":0,"date":1910},
{"name":"Seagull","value":1,"date":1910},
{"name":"Sparrow","value":0,"date":1910},
{"name":"Owl","value":1,"date":1910}
],
[
{"name":"Blackbird","value":0,"date":1920},
{"name":"Seagull","value":1,"date":1920},
{"name":"Sparrow","value":0,"date":1920},
{"name":"Owl","value":1,"date":1920},
{"name":"Eagle","value":0,"date":1920},
{"name":"Albatross","value":2,"date":1920}
]
]
No matter what I have tried, I always end up with all the dates I add to the objects being equal to the last value (1920 here). I understand that the objects are copied by reference only. I have tried using array.map() (like in the answer given here, but my question was not formulated right), but I still get the same problem.
EDIT
Here's one example of code I've tried :
var temp = [];
var b = data.map(function(c, index, main) {
var year = c.date;
temp = [];
main.slice(0, index + 1).map(function(d){
var t = d.data.map(function(e){
e.date = year;
return e;
});
temp = temp.concat(t);
});
return temp;
});
console.log(b);

Here's a working example:
You need to clone the object in order to "break" the reference.
var data = [
{
"date":1900,
"data":[
{"name":"Blackbird","value":0},
{"name":"Seagull","value":1},
{"name":"Sparrow","value":0}
]
},
{
"date":1910,
"data":[
{"name":"Owl","value":1}
]
},
{
"date":1920,
"data":[
{"name":"Eagle","value":0},
{"name":"Albatross","value":2}
]
}
];
var incremental = [];
var dataHistory = null;
for(i = 0; i < data.length; i++){
var temp = dataHistory ? dataHistory.slice() : []; //.slice to clone array
//Replace all values with current date.
for(var j = 0; j < temp.length; j++){
temp[j] = JSON.parse(JSON.stringify(temp[j])); //Clone object
temp[j].date = data[i].date;
}
//Add current date to object.
for(var j = 0; j < data[i].data.length; j++){
var aux = {
name: data[i].data[j].name,
value: data[i].data[j].value,
date: data[i].date
};
temp.push(aux);
}
dataHistory = temp;
incremental.push(temp);
}
document.body.innerHTML = '<pre>' + JSON.stringify(incremental, null, 4) + '</pre>';
If you're using jQuery you can replace:
temp[j] = JSON.parse(JSON.stringify(temp[j]));
With:
temp[j] = $.extend({}, temp[j]);

Try this one:
var data = [
{"date":1900,"data":[
{"name":"Blackbird","value":0},
{"name":"Seagull","value":1},
{"name":"Sparrow","value":0}
]},
{"date":1910,"data":[
{"name":"Owl","value":1}
]},
{"date":1920,"data":[
{"name":"Eagle","value":0},
{"name":"Albatross","value":2}
]}
];
var result = data.map(function(item) {
var replacement = [];
for (var key in item.data) {
var subItem = item.data[key];
subItem.date = item.date;
replacement.push(subItem);
}
return replacement;
});
document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 3) + '</pre>';

Use map, iterate over the inner array, and set the date property to each object etc.
var data = [
{"date":1900,"data":[
{"name":"Blackbird","value":0},
{"name":"Seagull","value":1},
{"name":"Sparrow","value":0}
]},
{"date":1910,"data":[
{"name":"Owl","value":1}
]},
{"date":1920,"data":[
{"name":"Eagle","value":0},
{"name":"Albatross","value":2}
]}
]
data = data.map(function(obj, i, arr) {
var o = [];
arr.slice(0, i).forEach(function(item) {
item.data.forEach(function(data) {
o.push(Object.assign({}, data))
});
});
return o.concat(obj.data.map(function(item) { item.date = obj.date; return item }));
});
document.body.innerHTML = '<pre>' + JSON.stringify(data, null, 4) + '</pre>';
Object.assign with polyfill

Related

how to make array of object using an array?

I have one array
var ar=['aa','cc','po']
I want to push objects in new array after checking the value of given array .In other words
I have these given conditions
var ar=['aa','cc','po']
var arr =[{name:"po"},{name:'aa'},{name:'cc'}];
Expected Output in new Array
[{name:'aa'},{name:'cc'},{name:"po"}]
As "aa" in in 0 index then I added object whose name property aa.
I try like this .but I used two for look .is there any simple way to do this
FIDDLE
var newArr=[];
for(var i=0;i<ar.length ;i++){
var text =ar[i];
for(var j=0;j<arr.length ;j++){
var obj =arr[j];
console.log(obj.name);
/*if(obj.name===text){
newArr.push(obj);
}*/
}
}
console.log(newArr);
This is a proposal in two part, first build an object with the reference to the items of arr and the create a new array with the given items of ar.
var ar = ['aa', 'cc', 'po'],
arr = [{ name: "po" }, { name: 'aa' }, { name: 'cc' }],
object = Object.create(null),
result = [];
arr.forEach(function (a) {
object[a.name] = a;
});
ar.forEach(function (a) {
object[a] && result.push(object[a]);
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Using forEach iterator and generate object reference based on name and then generate result array using map()
var ar = ['aa', 'cc', 'po']
var arr = [{
name: "po"
}, {
name: 'aa'
}, {
name: 'cc'
}];
var ref = {};
// generating object reference with name property
arr.forEach(function(v) {
ref[v.name] = v;
});
// generating result array
// or you can use forEach as #NinaScholz answer
var res = ar.map(function(v) {
return ref[v];
}).filter(function(v) { // use filter to avoid null values , in case of missing elements
return v != null;
});
document.write('<pre>' + JSON.stringify(res, null, 3) + '</pre>');
Try this:
function convert(source) {
var
obj = [],
i;
for (i = 0; i < source.length; ++i) {
obj.push({name: source[i]});
}
return obj;
}
convert(['aa', 'bb', 'cc']); // [{name:'aa'},{name:'bb'},{name:'cc'}]
This would work if you want to assign values from array in sequence:
var ar=['aa','cc','po']
var arr =[{name:"po"},{name:'aa'},{name:'cc'}];
arr.map(function(obj,key){
obj.name = ar[key];
});
console.log(arr);
Do like this
var ar = ['aa', 'cc', 'po']
var arr = [{ name: "po"}, { name: 'aa'}, { name: 'cc'}];
$.each(ar, function(i, v) {
arr[i].name = v;
});
console.log(arr)
Fiddle
var array=['a','b','c'];
var arrayObj=[];
for(var i=0;i<array.length;i++){
var obj={};
obj.name=array[i];
arrayObj.push(obj);
}
console.log(JSON.stringify(arrayObj));
Output:
[{"name":"a"},{"name":"b"},{"name":"c"}]
I guess this is one very functional way of doing this job with no more than an assignment line. However Anoop Joshi's answer is more elegant provided that the ar array is shorter than equal to in length to the arr array.
var arr = ['aa','cc','po'],
ar = [{name:"po"},{name:'aa'},{name:'cc'}],
res = arr.map(e => ar[ar.findIndex(f => f.name == e)]);
document.write("<pre>" + JSON.stringify(res) + "</pre>");

Filter unique array values and sum values

I have the following js array:
for(var j = 0; j < array.length; j++){
arr.push([array[j][0],array[j][1],array[j][2]]);
}
And it translates into this:
Number, type, qty
[[12345, "product", "10"],[12345, "product", "15"],[1234567, "other", "10"]]
What I've been trying to do is to filter the unique product number array[j][0] and sum the qty array[j][2] if there's more than one and I was able to do the unique filter by doing the following:
for(var o = 0; o < arr.length; o++){
if (!n[arr[o][1]]){
n[arr[o][1]] = true
r.push(arr[o]);
}
}
I would like your help to figure this out.. What I'm expecting to achieve is something like this:
[[12345, "product", "25"],[1234567, "other", "10"]]
Since product 12345 was repeated I only need to display it once and sum the qty of the other products with the same product number.
var productIndex = {};
var result = [];
for (var i = 0; i < arr.length; i++) {
var productId = arr[i][0];
if (productIndex[productId] === undefined) {
productIndex[productId] = result.length;
result.push(arr[i]);
} else {
var index = productIndex[productId];
result[index][2] = String(+result[index][2] + +arr[i][2]);
}
}
I am sure there are better ways. But I just changed it to an object, added them and changed it back to an array. Here you go:
https://jsfiddle.net/ct6to1Lv/
var a = [[12345, "product", "10"],[12345, "product", "15"],[1234567, "other", "10"]];
var b = {};
var c = [];
for(var i = 0; i < a.length; i++) {
if(!b.hasOwnProperty(a[i][0])) {
b[a[i][0]] = {};
b[a[i][0]]['qty'] = 0;
}
b[a[i][0]]['id'] = a[i][0];
b[a[i][0]]['name'] = a[i][1];
b[a[i][0]]['qty'] += parseInt(a[i][2]);
}
for(key in b) {
c[c.length] = [b[key]['id'], b[key]['name'], b[key]['qty']];
}
$(function(){
$('#console').append(a.toString()+'<br />');
$('#console').append(JSON.stringify(b)+'<br />');
$('#console').append(c.toString());
});
var arr = [[12345, "product", "10"],[12345, "product", "15"],[1234567, "other", "10"]];
var obj = {};
arr.forEach(function(e){
var t = e[0];
if(obj[t]) {
obj[t][2] += +e[2];
} else {
t = [];
t[0] = e[0];
t[1] = e[1];
t[2] = +e[2];
obj[e[0]] = t;
}
});
var res = [];
Object.keys(obj).forEach(function(k) {
res.push(obj[k]);
});
console.log(res);
Result:
[ [ 12345, 'product', 25 ], [ 1234567, 'other', 10 ] ]
To complete the possibillities, here a solution with a temporary object, which is hidden in this.
var data = [[12345, "product", "10"], [12345, "product", "15"], [1234567, "other", "10"]],
result = function (data) {
var r = [];
data.forEach(function (a) {
if (!this[a[0]]) {
this[a[0]] = [a[0], a[1], 0];
r.push(this[a[0]]);
}
this[a[0]][2] += +a[2];
}, {});
return r;
}(data);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
See Array.prototype.reduce() and Array.prototype.sort()
var list = [[12345, "product", "10"], [12345, "product", "15"], [1234567, "other", "10"], [12345, "product", "5"]];
//first we sort the array by id
//#pv = previous value; #cv = current value
list.sort(function(pv, cv) {
var a = +pv[0],
b = +cv[0];
return a - b;
});
//reduce the array for repeated elements
//#pv = previous value; #cv = current value
var reduced = list.reduce(function (pv, cv) {
//slice keeps reference when element is an object/array
var last = pv.slice(-1)[0];
if (last === undefined) return [cv];
//compares the id
if (last[0] == cv[0])
last[2] = +last[2] + (+cv[2]); //sums values
else pv.push(cv); //order elements
return pv;
}, []); //[] initial value for #pv
console.log(reduced);

Creating custom object from array

I have an array with below elements. I am trying to create an object from the array
var arr = [
'find({ qty: { $lt: 20 } } )',
'limit(5)',
'skip(0)'
]
Below is my code. where I am getting only values as the output. Any help on this will be helpful
for (var i = 0; i < arr.length; i++) {
var res = arr[i].search(/\(/ig)
if (res!= -1) {
var result = arr[i].split("(");
result = result[1].slice(0, -1))
}
}
Expected Output
{
"action": "find",
"value": "{ qty: { $lt: 20 } }",
"limit": 5,
"skip": 0
}
match is better than split for this kind of stuff
var arr = [
'find({ qty: { $lt: 20 } } )',
'limit(5)',
'skip(0)'
]
var obj = {};
arr.forEach(function(x, n) {
var m = x.match(/(\w+)\(\s*(.+?)\s*\)/);
if(n == 0) {
obj.action = m[1];
obj.value = m[2];
} else
obj[m[1]] = m[2];
});
document.write("<pre>" + JSON.stringify(obj,0,3));
see this fiddle
Just check if element is first in array, if yes, set action and value keys to splitted array, else just assign splitted values to key and value respectively
var arr = [
'find({ qty: { $lt: 20 } } )',
'limit(5)',
'skip(0)'
]
var result = {};
for (var i = 0; i < arr.length; i++) {
var res = arr[i].split("(")
console.log(res)
result[res[0]] = res[1].split(')')[0]
}
document.write(JSON.stringify(result))

Javascript object search

I have this code: (it reads a folder of mp3 files and retrieves all paths)
var base = "../media/audio/";
var arr1 = [
{path:"../media/audio/Numbers/Cat1/01.mp3"},
{path:"../media/audio/Numbers/Cat1/02.mp3"},
{path:"../media/audio/Numbers/Cat1/03.mp3"},
{path:"../media/audio/Numbers/Cat1/04.mp3"},
{path:"../media/audio/Letters/Cat1/01.mp3"},
{path:"../media/audio/Letters/Cat1/02.mp3"},
{path:"../media/audio/Letters/Cat1/03.mp3"},
{path:"../media/audio/Color/Cat1/01.mp3"},
{path:"../media/audio/Color/Cat1/02.mp3"},
{path:"../media/audio/Color/Cat1/03.mp3"}
];
I want to get this:
var arr2 = [
[{
category:"Numbers",
path:[
{path:"../media/audio/Numbers/Cat1/01.mp3"},
{path:"../media/audio/Numbers/Cat1/02.mp3"},
{path:"../media/audio/Numbers/Cat1/03.mp3"},
{path:"../media/audio/Numbers/Cat1/04.mp3"}
]
}],
[{
category:"Letters",
path:[
{path:"../media/audio/Letters/Cat1/01.mp3"},
{path:"../media/audio/Letters/Cat1/02.mp3"},
{path:"../media/audio/Letters/Cat1/03.mp3"}
]
}],
[{
category:"Color",
path:[
{path:"../media/audio/Color/Cat1/01.mp3"},
{path:"../media/audio/Color/Cat1/02.mp3"},
{path:"../media/audio/Color/Cat1/03.mp3"}
]
}]
];
Find every category after the 'base' string, split them in array, inside each array and object with category and path property.
Here you go.
var output = document.getElementById("output");
function splitSearch(base, arr1) {
var categoryList = {};
var baseLen = base.length;
// Split paths into categories
arr1.forEach(function(inPath) {
var subPath = inPath.path.substr(baseLen);
var category = subPath.split("/")[0];
if (!categoryList.hasOwnProperty(category)) {
categoryList[category] = [];
}
categoryList[category].push(inPath);
});
// Transform categoryList into array format requested
var arr2 = [];
for (var category in categoryList) {
arr2.push({ category: category, path: categoryList[category] });
}
return arr2;
}
var base = "../media/audio/";
var arr1 = [
{path:"../media/audio/Numbers/Cat1/01.mp3"},
{path:"../media/audio/Numbers/Cat1/02.mp3"},
{path:"../media/audio/Numbers/Cat1/03.mp3"},
{path:"../media/audio/Numbers/Cat1/04.mp3"},
{path:"../media/audio/Letters/Cat1/01.mp3"},
{path:"../media/audio/Letters/Cat1/02.mp3"},
{path:"../media/audio/Letters/Cat1/03.mp3"},
{path:"../media/audio/Color/Cat1/01.mp3"},
{path:"../media/audio/Color/Cat1/02.mp3"},
{path:"../media/audio/Color/Cat1/03.mp3"}
];
var result = splitSearch(base, arr1);
output.innerHTML += JSON.stringify(result);
<div id="output" />
This is what you are looking for:
var arr1 = [
{path:"../media/audio/Numbers/Cat1/01.mp3"},
{path:"../media/audio/Numbers/Cat1/02.mp3"},
{path:"../media/audio/Numbers/Cat1/03.mp3"},
{path:"../media/audio/Numbers/Cat1/04.mp3"},
{path:"../media/audio/Letters/Cat1/01.mp3"},
{path:"../media/audio/Letters/Cat1/02.mp3"},
{path:"../media/audio/Letters/Cat1/03.mp3"},
{path:"../media/audio/Color/Cat1/01.mp3"},
{path:"../media/audio/Color/Cat1/02.mp3"},
{path:"../media/audio/Color/Cat1/03.mp3"}
];
var basePath = "\.\.\/media\/audio\/";
var regex = new RegExp('^' + basePath + '(.*?)\/');
var categories = {}, arr2 = [];
for (var i=0, x=arr1.length; i < x; i++) {
var category = arr1[i].path.match(regex)[1];
if (!categories[category]) {
arr2.push({
category : category,
path : []
});
categories[category] = true;
}
for (var ii=0, l = arr2.length; ii < l; ii++) {
if (arr2[ii].category == category) {
arr2[ii].path.push(arr1[i]);
break;
}
}
}
Could probably be cleaned up a bit but should get you where you need to go

Find index in array of objects

I would like to find index in array. Positions in array are objects, and I want to filter on their properties. I know which keys I want to filter and their values. Problem is to get index of array which meets the criteria.
For now I made code to filter data and gives me back object data, but not index of array.
var data = [
{
"text":"one","siteid":"1","chid":"default","userid":"8","time":1374156747
},
{
"text":"two","siteid":"1","chid":"default","userid":"7","time":1374156735
}
];
var filterparams = {userid:'7', chid: 'default'};
function getIndexOfArray(thelist, props){
var pnames = _.keys(props)
return _.find(thelist, function(obj){
return _.all(pnames, function(pname){return obj[pname] == props[pname]})
})};
var check = getIndexOfArray(data, filterparams ); // Want to get '2', not key => val
Using Lo-Dash in place of underscore you can do it pretty easily with _.findIndex().
var index = _.findIndex(array, { userid: '7', chid: 'default' })
here is thefiddle hope it helps you
for(var intIndex=0;intIndex < data.length; intIndex++){
eachobj = data[intIndex];
var flag = true;
for (var k in filterparams) {
if (eachobj.hasOwnProperty(k)) {
if(eachobj[k].toString() != filterparams[k].toString()){
flag = false;
}
}
}
if(flag){
alert(intIndex);
}
}
I'm not sure, but I think that this is what you need:
var data = [{
"text":"one","siteid":"1","chid":"default","userid":"8","time":1374156747
}, {
"text":"two","siteid":"1","chid":"default","userid":"7","time":1374156735
}];
var filterparams = {userid:'7', chid: 'default'};
var index = data.indexOf( _.findWhere( data, filterparams ) );
I don't think you need underscore for that just regular ole js - hope this is what you are looking for
var data = [
{
"text":"one","siteid":"1","chid":"default","userid":"8","time":1374156747
},
{
"text":"two","siteid":"1","chid":"default","userid":"7","time":1374156735
}
];
var userid = "userid"
var filterparams = {userid:'7', chid: 'default'};
var index;
for (i=0; i < data.length; i++) {
for (prop in data[i]) {
if ((prop === userid) && (data[i]['userid'] === filterparams.userid)) {
index = i
}
}
}
alert(index);

Categories