Comparing 2 array values push only first result - javascript

I have an array which i need to compare it's values - and if there are duplication - i want to store them in array, for example :
obj1 = [{"manager_id":1,"name":"john"},{"manager_id":1,"name":"kile"},
{"manager_id":2,"name":"kenny"},
{"manager_id":4,"name":"stan"}]
obj2 = [{"employees_id":1,"name":"dan"},
{"employees_id":1,"name":"ben"},{"employees_id":1,"name":"sarah"},
{"employees_id":2,"name":"kelly"}]
If "manger_id" === "employees_id - then the result would be :
// {1:[{"manager_id":1,"name":"john"},{"manager_id":1,"name":"kile"},
{"employees_id":1,"name":"dan"}, {"employees_id":1,"name":"ben"},
{"employees_id":1,"name":"sarah"}]};
I've tried :
var obj1 = [{
"manager_id": 1,
"name": "john"
}, {
"manager_id": 1,
"name": "kile"
}, {
"manager_id": 2,
"name": "kenny"
}, {
"manager_id": 4,
"name": "stan"
}];
var obj2 = [{
"employees_id": 1,
"name": "dan"
}, {
"employees_id": 1,
"name": "ben"
}, {
"employees_id": 1,
"name": "sarah"
}, {
"employees_id": 2,
"name": "kelly"
}];
var res = obj1.concat(obj2).reduce(function(r, o) {
r[o.manager_id] = r[o.employees_id] || [];
r[o.manager_id].push(o);
return r;
}, {});
console.log(res);
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
As you can the results of the "manager_id" aren't added - only one - when there should be more
if manager_id === employees_id // should output in the first key
{1:[{"manager_id":1,"name":"john"},{"manager_id":1,"name":"kile"},
{"employees_id":1,"name":"dan"}, {"employees_id":1,"name":"ben"},
{"employees_id":1,"name":"sarah"}]};
As you can see there are several common id's

r[o.manager_id] = r[o.employees_id] || []; in this statement if a manager didn't have an employee_id the array was being reset for that id.
One way doing it right is this:
var res = obj1.concat(obj2).reduce(function(r, o) {
var id;
if(o.hasOwnProperty('manager_id')) {
id = o['manager_id'];
}
else {
id = o['employees_id'];
}
r[id] = r[id] || [];
r[id].push(o);
return r;
}, {});

The problem relies on this line:
r[o.manager_id] = r[o.employees_id] || [];
You should have in mind that some objects in your arrays have the manager_id and some other don't, they have the employees_id instead, so you have to evaluate that first with this line:
var itemId = o.manager_id || o.employees_id;
Try this code:
var res = obj1.concat(obj2).reduce(function(r, o) {
var itemId = o.manager_id || o.employees_id;
r[itemId] = r[itemId] || [];
r[itemId].push(o);
return r;
}, {});

Related

JavaScript get unique array object data by 2 object unique

I have problem with find uniqueness by 2 value. I want do something like SQL GROUP BY Tag_No and PlatformID. I want find unique value by Tag_No and PlayformID where both value can't be duplicate
I have tried something like below, but it only works for one unique 'Tag_No'
var NewTag = [
{Tag_No:'xxx01',PlatformID:'12',Details:'example1'},
{Tag_No:'xxx02',PlatformID:'13',Details:'example2'},
{Tag_No:'xxx03',PlatformID:'14',Details:'example3'},
{Tag_No:'xxx05',PlatformID:'5',Details:'example4'},
{Tag_No:'xxx05',PlatformID:'12',Details:'example5'},
{Tag_No:'xxx05',PlatformID:'12',Details:'example6'},
]
var tmp = [];
var result = [];
if (NewTag !== [] /* any additional error checking */ ) {
for (var i = 0; i < NewTag.length; i++) {
var val = NewTag[i];
if (tmp[val.Tag_No] === undefined ) {
tmp[val.Tag_No] = true;
result.push(val);
}
}
}
console.log('result',result)
expected value is
result=[{Tag_No:'xxx01',PlatformID:'12',Details:'example1'},
{Tag_No:'xxx02',PlatformID:'13',Details:'example2'},
{Tag_No:'xxx03',PlatformID:'14',Details:'example3'},
{Tag_No:'xxx05',PlatformID:'5',Details:'example4'},
{Tag_No:'xxx05',PlatformID:'12',Details:'example5'},
]
use array.filter instead.
This filters your array on duplicates no matter what structure you have.
Reference
var NewTag = [
{Tag_No:'xxx01',PlatformID:'12',Details:'example'},
{Tag_No:'xxx02',PlatformID:'13',Details:'example'},
{Tag_No:'xxx03',PlatformID:'14',Details:'example'},
{Tag_No:'xxx05',PlatformID:'5',Details:'example'},
{Tag_No:'xxx05',PlatformID:'12',Details:'example'},
{Tag_No:'xxx05',PlatformID:'12',Details:'example'},
]
const uniqueArray = NewTag.filter((value, index) => {
const _value = JSON.stringify(value);
return index === NewTag.findIndex(obj => {
return JSON.stringify(obj) === _value;
});
});
console.log('result',uniqueArray)
You can use hash grouping approach:
const data = [{Tag_No:'xxx01',PlatformID:'12',Details:'example'},{Tag_No:'xxx02',PlatformID:'13',Details:'example'},{Tag_No:'xxx03',PlatformID:'14',Details:'example'},{Tag_No:'xxx05',PlatformID:'5',Details:'example'},{Tag_No:'xxx05',PlatformID:'12',Details:'example'},{Tag_No:'xxx05',PlatformID:'12',Details:'example'}];
const result = Object.values(data.reduce((acc, item) => {
const hash = [item.Tag_No, item.PlatformID].join('---');
acc[hash] ??= item;
return acc;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }
Here is my solution:
let NewTag = [
{Tag_No:'xxx01',PlatformID:'12',Details:'example'},
{Tag_No:'xxx02',PlatformID:'13',Details:'example'},
{Tag_No:'xxx03',PlatformID:'14',Details:'example'},
{Tag_No:'xxx05',PlatformID:'5',Details:'example'},
{Tag_No:'xxx05',PlatformID:'12',Details:'example'},
{Tag_No:'xxx05',PlatformID:'12',Details:'example'},
]
let temp=[]
let result=[];
NewTag.forEach(tag=>{
let key=tag.Tag_No+"\t"+tag.PlatformID;
if (!temp.includes(key)){
temp.push(key);
result.push(tag)
}
});
console.log(result)
You could use Set to check for uniqueness
const NewTag = [
{ Tag_No: "xxx01", PlatformID: "12", Details: "example" },
{ Tag_No: "xxx02", PlatformID: "13", Details: "example" },
{ Tag_No: "xxx03", PlatformID: "14", Details: "example" },
{ Tag_No: "xxx05", PlatformID: "5", Details: "example" },
{ Tag_No: "xxx05", PlatformID: "12", Details: "example" },
{ Tag_No: "xxx05", PlatformID: "12", Details: "example" },
]
const uniquePairSet = new Set()
const res = NewTag.reduce((acc, el) => {
const Tag_No_PlatformID = `${el.Tag_No}-${el.PlatformID}`
if (!uniquePairSet.has(Tag_No_PlatformID)) {
uniquePairSet.add(Tag_No_PlatformID)
acc.push(el)
}
return acc
}, [])
console.log("result", res)
References
Set

parse array of object that contains JSON elements

First let me break down the data:
I have an array that contains 3 elements...
Each Element is an object with name and arrayOfJSON as keys...
Inside arrayOfJSON there could be any number of JSON strings as elements...
I need to capture the position where Alex#gmail occurs for both the array mess and arrayOfJSON
Result Should Be:
position_of_mess = [0,2]
position_of_arrayOfJSON_for_position_of_mess_0 = [0]
position_of_arrayOfJSON_for_position_of_mess_2 = [1]
What I'm trying at the moment:
For loop through mess, for loop through arrayOfJSON , and JSON.parse() for Alex#gmail.
going to take me a few mins to update.
If y'all think it can be done without a for-loop let me know.
Update: almost there
mess = [{
"name": "user1",
"arrayOfJSON": `[{"email":"Alex#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
},
{
"name": "user2",
"arrayOfJSON": `[{"email":"Chris#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
},
{
"name": "user3",
"arrayOfJSON": `[{"email":"bob#gmail","hobby":"coocking"},{"email":"Alex#gmail","hobby":"coding"}]`
}
]
console.log(mess)
for (i = 0; i < mess.length; i++) {
console.log(JSON.parse(mess[i].arrayOfJSON))
for (m = 0; m < (JSON.parse(mess[i].arrayOfJSON)).length; m++) {
console.log("almost")
console.log((JSON.parse(mess[i].arrayOfJSON))[m])
}
}
mess = [{
"name": "user1",
"arrayOfJSON": `[{"email":"Alex#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
},
{
"name": "user2",
"arrayOfJSON": `[{"email":"Chris#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
},
{
"name": "user3",
"arrayOfJSON": `[{"email":"bob#gmail","hobby":"coocking"},{"email":"Alex#gmail","hobby":"coding"}]`
}
]
console.log(mess)
holdMessPosition = []
for (i = 0; i < mess.length; i++) {
var pos = (JSON.parse(mess[i].arrayOfJSON)).map(function(e) {
return e.email;
})
.indexOf("Alex#gmail");
console.log("user position is " + pos);
if (pos !== -1) {
holdMessPosition.push(i)
}
}
console.log(holdMessPosition)
Parse your data
You want to be able to access keys inside the inner object "string"
Traverse your data
While visiting key-value pairs, build a scope thet you can later return
// Adapted from: https://gist.github.com/sphvn/dcdf9d683458f879f593
const traverse = function(o, fn, scope = []) {
for (let i in o) {
fn.apply(this, [i, o[i], scope]);
if (o[i] !== null && typeof o[i] === "object") {
traverse(o[i], fn, scope.concat(i));
}
}
}
const mess = [{
"name": "user1",
"arrayOfJSON": `[{"email":"Alex#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
}, {
"name": "user2",
"arrayOfJSON": `[{"email":"Chris#gmail","hobby":"coding"},{"email":"bob#gmail","hobby":"coocking"}]`
}, {
"name": "user3",
"arrayOfJSON": `[{"email":"bob#gmail","hobby":"coocking"},{"email":"Alex#gmail","hobby":"coding"}]`
}];
// Parse...
mess.forEach(item => {
if (item.arrayOfJSON) {
item.arrayOfJSON = JSON.parse(item.arrayOfJSON);
}
});
traverse(mess, (key, value, scope) => {
if (value === 'Alex#gmail') {
console.log(
`Position: mess[${scope.concat(key).map(k => isNaN(k) ? `'${k}'` : k).join('][')}]`
);
}
});
.as-console-wrapper {
top: 0;
max-height: 100% !important;
}

How to create a nested object from data using JavaScript?

Before
This is an object with multiple rows:
{
"functions": [
{
"package_id": "2",
"module_id": "2",
"data_id": "2"
},
{
"package_id": "1",
"module_id": "1",
"data_id": "2"
},
{
"package_id": "2",
"module_id": "3",
"data_id": "3"
}
]
}
Desired result
I want this to return into a "nested" Object like below, without duplicates:
{
"packages": [
{
"package_id": "2",
"modules": [
{
"module_id": "2",
"data": [
{
"data_id": "2"
}
]
},
{
"module_id": "3",
"data": [
{
"data_id": "3"
}
]
}
]
},{
"package_id": "1",
"modules": [
{
"module_id": "1",
"data": [
{
"data_id": "2"
}
]
}
]
}
]
}
I've already tried loops inside loops, with constructing multiple arrays and objects. Which causes duplicates or overriding objects into single ones. Is there a more generic way to generate this with JavaScript? (It's for an Angular (6) project.
Example 1
getFunctionPackage() {
var fList = this.functionList;
var dArr = [];
var dObj = {};
var pArr = [];
var pObj = {};
var mArr = [];
var mObj = {};
for (var key in fList) {
pObj['package_id'] = fList[key]['package_id'];
mObj['module_id'] = fList[key]['module_id'];
dObj['data_id'] = fList[key]['data_id'];
for (var i = 0; i < pArr.length; i++) {
if (pArr[i].package_id != pObj['package_id']) {
pArr.push(pObj);
}
for (var x = 0; x < mArr.length; x++) {
if (pArr[i]['modules'][x].module_id != mObj['module_id']) {
mArr.push(mObj);
}
for (var y = 0; y < dArr.length; y++) {
if (pArr[i]['modules'][x]['datas'][y].data_id != dObj['data_id']) {
dArr.push(dObj);
}
}
}
}
if (dArr.length == 0) {
dArr.push(dObj);
}
mObj['datas'] = dArr;
if (mArr.length == 0) {
mArr.push(mObj);
}
pObj['modules'] = mArr;
if (pArr.length == 0) {
pArr.push(pObj);
}
dObj = {};
mObj = {};
pObj = {};
}
}
Example 2:
Results in skipping cause of the booleans
var fList = this.functionList;
var dArr = [];
var dObj = {};
var pArr = [];
var pObj = {};
var mArr = [];
var mObj = {};
var rObj = {};
for (var key in fList) {
pObj['package_id'] = fList[key]['package_id'];
mObj['module_id'] = fList[key]['module_id'];
dObj['data_id'] = fList[key]['data_id'];
var pfound = false;
var mfound = false;
var dfound = false;
for (var i = 0; i < pArr.length; i++) {
if (pArr[i].package_id == pObj['package_id']) {
for (var x = 0; x < mArr.length; x++) {
if (pArr[i]['modules'][x].module_id == mObj['module_id']) {
for (var y = 0; y < dArr.length; y++) {
if (pArr[i]['modules'][x]['datas'][y].data_id == dObj['data_id']) {
dfound = true;
break;
}
}
mfound = true;
break;
}
}
pfound = true;
break;
}
}
if (!dfound) {
dArr.push(dObj);
mObj['datas'] = dArr;
dObj = {};
}
if (!mfound) {
mArr.push(mObj);
pObj['modules'] = mArr;
mObj = {};
}
if (!pfound) {
pArr.push(pObj);
pObj = {};
}
dArr = [];
mArr = [];
}
rObj['packages'] = pArr;
console.log(rObj);
Here's a more generic approach using Array#reduce() to create a grouped object based on the package id as keys. You can use any loop to build this same object ...for() or forEach() for example.
Then use Object.values() to get the final array from that grouped object
Using methods like Array#find() simplifies traversing to see if a module exists already or not within each package
const grouped = data.functions.reduce((a, c )=>{
// if group object doesn't exist - create it or use existing one
a[c.package_id] = a[c.package_id] || {package_id : c.package_id, modules: [] }
// store reference to the group modules array
const mods = a[c.package_id].modules
// look within that group modules array to see if module object exists
let module = mods.find(mod => mod.module_id === c.module_id)
if(!module){
// or create new module object
module = {module_id: c.module_id, data:[]}
// and push it into modules array
mods.push(module);
}
// push new data object to module data array
module.data.push({data_id: c.data_id})
return a
}, {})
// create final results object
const res = { packages : Object.values(grouped) }
console.log(res)
.as-console-wrapper {max-height: 100%!important;}
<script>
const data = {
"functions": [{
"package_id": "2",
"module_id": "2",
"data_id": "2"
},
{
"package_id": "1",
"module_id": "1",
"data_id": "2"
},
{
"package_id": "2",
"module_id": "3",
"data_id": "3"
}
]
}
</script>

check to see if all objects in an array has a common property

I have an array of objects which I am trying to loop over and check for a common key if it exists for all objects. if the specific key does not exist for all objects I return false.
Here is my code
var x = [{
"item": "alpha",
"value": "red"
}, {
"item": "beta",
"value": "blue"
}, {
"item": "beta",
"value": "gama"
}]
function test(obj) {
var count = 0;
var out = false;
for (var i = 0; i < obj.length; i++) {
if (obj[i].hasOwnProperty('value')) {
count = i;
}
}
if (count == obj.length) {
out = true
}
}
console.log(test(x))
I am getting undefined. Cant figure out what am I missing here
A really simple way to do this is to use Array#every like this
var x = [{
"item": "alpha",
"value": "red"
}, {
"item": "beta",
"value": "blue"
}, {
"item": "beta",
"value": "gama"
}]
function test(obj) {
return obj.every(a => a.hasOwnProperty("value"));
}
console.log(test(x))
Update
As rightfully mentioned by this comment first.
Here can be the simple solution for this object:
var x = [{
"item": "alpha",
"value": "red"
}, {
"item": "beta",
"value": "blue"
}, {
"item": "beta",
"value": "gama"
}];
function test(obj) {
var keyCount = 0;
obj.forEach(function (item, index) {
item.hasOwnProperty('value') && ++keyCount;
});
return keyCount == obj.length;
}
console.log(test(x));
Here is my implementation, which finds every matching key, even nested keys, given a set of objects:
function recurse_obj(obj, cb, _stack = []) {
for (var k in obj) {
cb(k, obj[k], _stack);
if (obj.hasOwnProperty(k) && (obj[k] instanceof Object)) {
_stack.push(k);
recurse_obj(obj[k], cb, _stack);
_stack.pop();
}
}
}
function obj_all_keys(obj) {
var tmp = [];
recurse_obj(obj, (k, v, stack) => {
var ext = (stack.length) ? "." : "";
tmp.push(stack.join(".").concat(ext, k));
});
return tmp;
}
function key_intersection(...objs) {
var lookup = {};
objs.forEach(o => {
obj_all_keys(o).forEach(k => {
if (k in lookup === false)
lookup[k] = 0;
lookup[k]++;
});
});
for (var k in lookup)
if (lookup[k] !== objs.length)
delete lookup[k];
return lookup;
}
Here is the calling code:
var me = { name: { first: "rafael", last: "cepeda" }, age: 23, meta: { nested: { foo: { bar: "hi" } } } };
console.log(key_intersection(me, { name: { first: "hi" } }));
Output: { name: 2, 'name.first': 2 }
The object returned includes only the keys that are found in all the objects, the set intersection, the counts are from book-keeping, and not removed in the callee for performance reasons, callers can do that if need be.
Keys that are included in other nested keys could be excluded from the list, because their inclusion is implied, but I left them there for thoroughness.
Passing a collection (array of objects) is trivial:
key_intersection.apply(this, collection);
or the es6 syntax:
key_intersection(...collection);

How to map a javascript array to another javascript array

I have a constructor in JavaScript which contains 2 properties Key and Values array:
function Test(key, values) {
this.Key = key;
this.Values = values.map(values);
}
Then I created an array of Test objects:
var testObjectArray = [];
testObjectArray.push(new Test(1, ['a1','b1']), new Test(2, ['a1','b2']));
Now I want to map the testObjectArray to single key-value pair array which will be similar to :
[
{ "Key" : "1", "Value" : "a1" },
{ "Key" : "1", "Value" : "b1" },
{ "Key" : "2", "Value" : "a2" },
{ "Key" : "2", "Value" : "b2" },
]
How can I achieve this using array's map function?
I guess you are misunderstanding map(). Here is a very simple example:
a = [1, 2, 3]
b = a.map(function (i) { return i + 1 })
// => [2, 3, 4]
Here is the MDN documentation for map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map. So you should rethink the usage of map in your case. By the way - your example is not working, because values is not a function.
Here is a possible solution:
res = [];
a = [['a1','b1'],['a1','b2']];
for (var i = 0; i < a.length; ++i) {
for(var j = 0; j < a[i].length; ++j) {
res.push({"Key": i + 1 , "Value" : a[i][j]});
}
}
I'm sure there are other ways, but here's something with plain Javascript that does what you want:
http://jsfiddle.net/KXBRw/
function Test(key, values) {
this.Key = key;
this.Values = values;//values.map(values);
}
function getCombinedTests(testObjectArray) {
var all = [];
for (var i = 0; i < testObjectArray.length; i++) {
var cur = testObjectArray[i];
for (var j = 0; j < cur.Values.length; j++) {
all.push({"Key": ""+cur.Key, "Value": cur.Values[j]});
}
}
return all;
}
var testObjectArray1 = [];
testObjectArray1.push(new Test(1, ['a1','b1']), new Test(2, ['a1','b2']));
var combined = getCombinedTests(testObjectArray1);
console.log(combined);
You could use .reduce(), .concat() and .map() for this.
var result = testObjectArray.reduce(function(res, obj) {
return res.concat(obj.Values.map(function(val) {
return {"Key":obj.Key, "Value":val};
}));
}, []);
Not sure what values.map(values); was supposed to do though.
DEMO: http://jsfiddle.net/BWNGr/
[
{
"Key": 1,
"Value": "a1"
},
{
"Key": 1,
"Value": "b1"
},
{
"Key": 2,
"Value": "a1"
},
{
"Key": 2,
"Value": "b2"
}
]
If you're super strict about not creating unnecessary Arrays, you can tweak it a little and use .push() instead of .concat().
var result = testObjectArray.reduce(function(res, obj) {
res.push.apply(res, obj.Values.map(function(val) {
return {"Key":obj.Key, "Value":val};
}));
return res;
}, []);
DEMO: http://jsfiddle.net/BWNGr/1/
You can achieve this by using the following for each loop where each key value pair will be pushed to an array.
var mapped = [];
$.each(testObjectArray, function(key, value) {
for(x in value.Values) {
mapped.push({
Key: value.Key,
Value: x
});
}
});

Categories