Populate array compared to another array - javascript

I have these 2 arrays
var array1 = [{
id: "Test1",
value: "Beep"
}, {
id: "Test2",
value: "Meep"
}, {
id: "Test3",
value: "Sheep"
}];
var array2 = [{
id: "Test2"
}, {
id: "Test3"
}],
stuff2: [{
id: "Test1"
}, {
id: "Test3"
}],
stuff3: [{
id: "Test3"
}];
I am looking for a way to insert empty objects or null to the 2nd array so that the 2nd array looks something like this:
var array2 = [null, {
id: "Test2"
}, {
id: "Test3"
}],
stuff2: [{
id: "Test1"
}, null, {
id: "Test3"
}],
stuff3: [
null, null, {
id: "Test3"
}
];
This can't be ES6 since the code base I am working on it rather old (AngularJS 1.4).
I haven't been able to wrap my mind around this one. Any help is welcome.

I am making some assumptions about what you are actually trying to accomplish (based on your input and desired output). The idea is that for each key in the containing object (array as you called them), you check to see if the id of each element in the stuff, stuff2, etc. arrays is equal to the object's index in the array + 1. (i.e. stuff[0].id === "Test1"). If that is not the case, insert null into the array at that position and move forward. It would look like the following:
var array2 = {
stuff: [{
id: "Test2"
}, {
id: "Test3"
}],
stuff2: [{
id: "Test1"
}, {
id: "Test3"
}],
stuff3: [{
id: "Test3"
}]
};
function fillGaps(obj) {
var keys = Object.keys(obj);
keys.forEach(function (key) {
var arr = obj[key];
for(var i = 0; i < arr.length; i++) {
var id = arr[i].id;
if (id !== "Test" + (i+1)) {
arr.splice(i, 0, null);
}
}
});
return obj;
}
console.log(fillGaps(array2));

Related

Javascript compare two JSON arrays and return key of the unmatched value

I have two JSON arrays, would like to know the key which don't match. I don't need the value.
Example:
livetable: [
{ id: 1, name: "Sandra" },
{ id: 2, name: "John" },
],
backupTable: [
{ id: 1, name: "Sandra" },
{ id: 2, name: "Peter" },
],
I can get the key/value pair which is diffrent with this Lodash script:
difference = _.differenceWith(livetable,backupTable,_.isEqual)
But I would just need the key, in this example "name" for "id: 2" is not matching, so I would need to get the "name" key to new array/variable.
(Using VUE CLI)
EDIT: Added example of current code output.
var livetable = [{"id": 1, "name": "Sandra", "id": 2, "name": "John"}]
var backupTable = [{"id": 1, "name": "Sandra", "id": 2, "name": "Peter"}]
console.log(_.differenceWith(backupTable,livetable,_.isEqual))
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
This will output the key:value pair, but I would just need the key which is diffrent.
I think I understand what you're trying to do. There are some unknowns though, like what should happen if there is a missing record in the second data set?
This solution assumes each table of data has the same amount of records and the records have the same IDs.
// define data
const livetable = [
{ id: 1, name: "Sandra" },
{ id: 2, name: "John" }
]
const backupTable = [
{ id: 1, name: "Sandra" },
{ id: 2, name: "Peter" }
]
const getDifferentRecordsByID = (sourceRecords, compareRecords) => {
// simple utility function to return a record object matching by ID
const findComparisionRecord = id => compareRecords.find(compareRecord => compareRecord.id === id)
// using the utility function, we can filter out any mismatching records by comparing name
return sourceRecords
.filter(sourceRecord => sourceRecord.name !== findComparisionRecord(sourceRecord.id).name)
// then map over all the records and just pull out the ID
.map(record => record.id)
}
console.log(getDifferentRecordsByID(livetable, backupTable)) // [2]
Here is working VUE code for my problem.
Function returns [ "name" ], which is exactly what I need.
data() {
return {
livetable: [{ id: 1, name: "Sandra" },{ id: 2, name: "John" }],
backupTable: [{ id: 1, name: "Sandra" },{ id: 2, name: "Peter" }],
difColumns: null,
};
},
methods: {
test3() {
let resultArray = []
this.livetable.forEach((array1, index) => {
const array2 = this.backupTable[index];
resultArray.push(this._.reduce(array1, (result, value, key) => this._.isEqual(value, array2[key]) ? result : result.concat(key), []))
});
this.difColumns = resultArray[0]
}
},

How to get distinct properties value from array? [duplicate]

This question already has answers here:
Remove duplicates form an array
(17 answers)
Closed 5 years ago.
I have this array?
var arr = [{id:"1",Name:"Tom"},
{id:"2",Name:"Jon"},
{id:"3",Name:"Tom"},
{id:"4",Name:"Jack"}]
From array above I need to fecth all existing Names distinct.
var result = getNamesDistinct(arr);
The result should contain result is:
["Tom","Jon","Jack"];
My question is how to get all existing Names from arr distinct?
If Set is available, you can simply do
new Set(arr.map(obj => obj.Name))
(pass the set to Array.from if you need an array)
You can do it via Set object
const arr = [
{ id: "1", Name: "Tom" },
{ id: "2", Name: "Jon" },
{ id: "3", Name: "Tom" },
{ id: "4", Name: "Jack" }
];
const uniqueNames = [...new Set(arr.map(item => item.Name))];
console.log(uniqueNames);
Or you can iterate over the array and add condition to get only unique names.
const arr = [
{ id: "1", Name: "Tom" },
{ id: "2", Name: "Jon" },
{ id: "3", Name: "Tom" },
{ id: "4", Name: "Jack" }
];
const uniqueNames = arr.reduce(function(arr, item) {
if(arr.indexOf(item.Name) === -1) {
arr.push(item.Name);
}
return arr;
}, []);
console.log(uniqueNames);
you can try this
var array = [{
id: "1",
Name: "Tom"
}, {
id: "2",
Name: "Jon"
}, {
id: "3",
Name: "Tom"
}, {
id: "4",
Name: "Jack"
}]
function uniqueNames(array) {
var newArray = [];
array.forEach((value, key) => {
newArray.push(value.Name)
});
return newArray
}
var myNewArray = uniqueNames(array)

Dynamically convert array to tree-like structure

Can someone show me the most efficient way to convert an array to a tree-like structure?
var array= [
{id: "1", name: "header1"},
{id: "2", name: "header2"},
{id: "1.1", name: "subheader1.1"},
{id: "1.2", name: "subheader1.2"},
{id: "2.1", name: "subheader2.1"},
{id: "2.2", name: "subheader2.2"},
{id: "1.1.1", name: "subheader1detail1"},
{id: "2.1.1", name: "subheader2detail2"}
];
Result array must be like this:
var array = [{
id: "1",
name: "header1",
items: [{
id: "1.1",
name: "subheader1.1",
items: [{
id: "1.1.1",
name: "subheader1detail1",
}]
}, {
id: "1.2",
name: "subheader1.2"
}]
}, {
id: "2",
name: "header2",
items: [{
id: "2.1",
name: "subheader2.1",
items: [{
id: "2.1.1",
name: "subheader2detail2",
}]
}, {
id: "2.2",
name: "subheader2.2"
}]
}]
Thanks in advance
You could use a tree and build the nested array upon. This proposal needs a sorted list.
Basically it looks for the parent of a node and if a node has no parent, then a root node is found and inserted into the result array. If a parent is found, then the actual node is inserted into the items property of the parent.
var array = [{ id: "1", name: "header1" }, { id: "2", name: "header2" }, { id: "1.1", name: "subheader1.1" }, { id: "1.2", name: "subheader1.2" }, { id: "2.1", name: "subheader2.1" }, { id: "2.2", name: "subheader2.2" }, { id: "1.1.1", name: "subheader1detail1" }, { id: "2.1.1", name: "subheader2detail2" }],
result = [];
array.forEach(function (a) {
var parent = a.id.split('.').slice(0, -1).join('.');
this[a.id] = { id: a.id, name: a.name };
if (parent) {
this[parent] = this[parent] || {};
this[parent].items = this[parent].items || [];
this[parent].items.push(this[a.id]);
} else {
result.push(this[a.id]);
}
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can try something like this:
I have added comments to explain the logic
var array= [
{id: "1", name: "header1"},
{id: "2", name: "header2"},
{id: "1.1", name: "subheader1.1"},
{id: "1.2", name: "subheader1.2"},
{id: "2.1", name: "subheader2.1"},
{id: "2.2", name: "subheader2.2"},
{id: "1.1.1", name: "subheader1detail1"},
{id: "2.1.1", name: "subheader2detail2"},
];
var result = {};
// Sort in case values are not in order.
// This is to ensure parent is rendered before child
array.sort(function(a, b) {
return a.id > b.id ? 1 : a.id - b.id ? -1 : 0
})
// Loop over sorted array to parse
.forEach(function(el) {
// Check if element does not exists to prevent duplicate
if (!result[el.id]) {
// if parent, push it
if (el.id.indexOf('.') === -1)
result[el.id] = el;
// If child, compute depth and search object to push to
else {
var ids = el.id.split('.');
var _id = '';
// temp variable to hold position to push
var r = result[ids[0]];
for (var i = 1; i < ids.length; i++) {
// Compute the object id
_id = (_id ? _id + '.' : _id) + ids[i - 1];
// initialize items
r.items = r.items || [];
// search in items to get object if exist
var o = r.items.find(x => x.id === _id);
// if object exists, assign it to temp variable
// If not, push to parent
if (o) r = o;
}
if (r) {
r.items = r.items || [];
r.items.push(el);
}
}
}
})
console.log(result)
Note: I have changed structure to hold an object instead of an array
Was fiddling with the problem here - sharing across a solution using Array.prototype.reduce and a local hash table - also sorting the result. Cheers!
var array=[{id:"2",name:"header2"},{id:"1",name:"header1"},{id:"1.1",name:"subheader1.1"},{id:"1.2",name:"subheader1.2"},{id:"2.2",name:"subheader2.2"},{id:"2.1",name:"subheader2.1"},{id:"1.1.1",name:"subheader1detail1"},{id:"2.1.1",name:"subheader2detail2"}];
var result = array.sort(function(a,b) {
return a.id - b.id;
}).reduce(function(hash) {
return function(prev, curr) {
var keys = curr.id.split('.');
hash[curr.id] = hash[curr.id] || {};
hash[curr.id] = {id: curr.id,name: curr.name};
if (keys && keys.length > 1) {
keys.pop();
var key = keys.join('.');
hash[key].items = hash[key].items || [];
hash[key].items.push(hash[curr.id]);
} else {
prev.push(hash[curr.id]);
}
return prev;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper {top: 0;max-height: 100%!important;}

Merge nested array in object in Javascript

I need to merge 2 objects with nested arrays
var dest = {
id: "865",
arr: [{
id: "123",
value: "First" }]
};
var src = {
id: "865",
arr: [{
id: "456",
value: "Second" }]
};
to produce
merge = {
id: "865",
arr: [{id: "123",
value: "First"},
{id: "456",
value: "Second"}]
};
I tried using _.merge(dest, src) (using Lodash) and a couple of other methods, but seems like the 2nd object is overwriting the first one because it doesn't handle the nested array the way I want.
What is the best way to do this?
Thanks,
You can use Lodash _.mergeWith method:
var dest = {
id: "865",
arr: [{
id: "123",
value: "First"
}]
};
var src = {
id: "865",
arr: [{
id: "456",
value: "Second"
}]
};
var merge = _.mergeWith({}, src, dest, function(a, b) {
if (_.isArray(a)) {
return b.concat(a);
}
});
console.log(merge);
It allows you to pass a customizer in order to merge the array in a "custom" way.
Here's the fiddle. Hope it helps.
You can use Object.assign()
var dest = {
id: "865",
arr: [{
id: "123",
value: "First" }]
};
var src = {
id: "865",
arr: [{
id: "456",
value: "Second" }]
};
var merge = Object.assign({}, dest);
merge.arr.push(Object.assign({}, src.arr[0]));
src.arr[0].id = 789; // should not affect `merge.arr`
console.log(merge);
Without any libraries.
var dest = {
id: "865",
arr: [{
id: "123",
value: "First"
}]
};
var src = {
id: "865",
arr: [{
id: "456",
value: "Second"
}]
};
// 1
var resultOne = {
id: dest.id,
arr: src.arr.concat(dest.arr)
};
// 2
var resultTwo = Object.assign({}, src, {
arr: src.arr.concat(dest.arr)
});
// 3
var merge = function(obj1, obj2) {
return Object.keys(obj1).reduce(function(result, next) {
if (Array.isArray(obj1[next]) && Array.isArray(obj2[next])) {
result[next] = obj1[next].concat(obj2[next]);
} else if (obj1[next] && obj2[next]) {
result[next] = obj2[next];
}
return result;
}, {});
}
console.log(merge(src, dest));

how to convert array of object into object?

I have an array of object and i cant convert it into an object. The array of object that i have is as below:
var x = [{
name: "a",
items: [{
name: "b",
items: [{
name: "c"
}]
}]
},
{
name: "d",
items: [{
name: "e",
items: [{
name: "f"
}]
}]
}];
and i want to convert it into object like this:
{
name: "a",
items: [{
name: "b",
items: [{
name: "c"
}]
}]
},{
name: "d",
items: [{
name: "e",
items: [{
name: "f"
}]
}]
}
I used one of the stackoverflow solution
function toObject(arr) {
var rv = {};
for (var i = 0; i < arr.length; ++i)
rv[i] = arr[i];
return rv;
}
But it convert as follows:
{
"0":{
"name":"a",
"items":[{"name":"b","items":[{"name":"c"}]}]},
"1":{
"name":"d",
"items":[{"name":"e","items":[{"name":"f"}]}]}
}
So, how to get the object in the format i gave?
The following is not one object
{
name: "a",
items: [{
name: "b",
items: [{
name: "c"
}]
}]
}, // this comma shows you that it's can't be one object.
{
name: "d",
items: [{
name: "e",
items: [{
name: "f"
}]
}]
}
You can't have an object with the two different properties of the same name.
You want to reduce the array into a single object:
var output = x.reduce(function(output, arrayItem) {
var key = arrayItem.name;
output[key] = arrayItem;
return output;
}, { });
maybe you want something like this
var x = [{
name: "a",
items: [{
name: "b",
items: [{
name: "c"
}]
}]
},
{
name: "d",
items: [{
name: "e",
items: [{
name: "f"
}]
}]
}];
function toObject(arr) {
var rv = {};
for (var i = 0; i < arr.length; ++i)
rv[arr[i].name] = { items: arr[i].items} ;
return rv;
}
console.log(toObject(x));
http://jsfiddle.net/jypahwj4/
One problem that your doing to run into is that when creating an object from that array you will have multiple keys with the same name so each name: will be overridden by the next one you try and add to the object. In your function because you are doing rv[i] and i is a number that is why you are getting the numbers in your newly created object.
A possible solution would be
function toObject(arr) {
var rv = {};
for (var i = 0; i < arr.length; ++i)
rv[arr[i].name] = arr[i].items;
return rv;
}
But this would make the key of the outer part of the object be equal to the name: of the original array of objects

Categories

Resources