Underscore.js get an array of unique objects - javascript

I have 2 arrays of objects. There are duplicates between the arrays. I want to merge them into 1 array of all unique objects (so no duplicates).
How can I do this by comparing the "id" of each object?
Underscore.js has a method called _.uniq(). It looks to be correct, but I can't get the syntax for the "iterator" argument correct.
var firstArray = [{ id: 1, name: "foo"}, { id: 2, name: "bar" }];
var secondArray = [{ id: 2, name: "boop" }, { id: 3, name: "baz" }];
firstArray.push(secondArray);
var myUniqueArray = _.uniq(firstArray, false, ???);
myUniqueArray // [{ id: 1, name: "foo"}, { id: 2, name: "bar" }, { id: 3, name: "baz" }];

You should be able to achieve this with _.uniq method used with second parameter of the property name to be used to filter items:
var firstArray = [{ id: 1, name: "foo"}, { id: 2, name: "bar" }];
var secondArray = [{ id: 2, name: "boop" }, { id: 3, name: "baz" }];
var result = _.uniq(firstArray.concat(secondArray), 'id');
alert(JSON.stringify(result, null, 4));
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

The following should do it:
var myUniqueArray = _.uniq(firstArray.concat(secondArray), false, function (obj) {
return obj.id;
});
The iteratee here will produce a value on which uniqueness is checked, in this case the id property value.
Here's a JSFiddle.

Related

Delete multiple objects in an array by id

I have a main array of objects with each object having some key/values as well as a "id" key with 1,2,3,4,5, etc
Now I have another array representing just id's (like [2,3])
I want to use this array to delete objects from the main array...so in this case, objects from the main array having id's 2 & 3 should be deleted
While I am aware of findBy(id), I am not sure if that can be used to delete multiple objects at once.
You can use filter. In the filter callback function check if the id is also there in id array by using includes
let idArr = [1, 2]
let obj = [{
id: 1,
name: 'abc'
},
{
id: 2,
name: 'abc'
},
{
id: 3,
name: 'abc'
},
{
id: 4,
name: 'abc'
}
];
let data = obj.filter(item => !idArr.includes(item.id));
console.log(data);
console.log(obj)
using filter might work well here. you could write something like:
var newArray = oldArray.filter(object => !ids.includes(object.id))
You can do it, like this:
[2,3].forEach(key => {
delete object[key];
})
You can use filter method for this.
Ex:
let id = 2;
let list = [{
Id: 1,
Name: 'a'
}, {
Id: 2,
Name: 'b'
}, {
Id: 3,
Name: 'c'
}];
let lists = list.filter(x => {
return x.Id != id;
})
console.log(lists);
Assuming you want to delete items from the original array by entirely removing the element from the array (and you don't want to get a new array), you can take advantage of
Array.splice
let idArr = [1, 2];
let obj = [{
id: 1
},
{
id: 2
},
{
id: 3
},
{
id: 4
}
];
for (let id of idArr) {
// look for the element by its id.
const objIdRef = obj.find(i => i.id === id);
// if it actually exists, splice it.
objIdRef && obj.splice(obj.indexOf(objIdRef), 1);
}
console.log(obj);
If the obj array is big, you might want to make a map from it before processing the id array, so that the complexing is reduced to O(1) when the delete process begins.
Perhaps This is what you want:
var arr= [{id:1, name: "foo"}, {id:2, name: "bar"}, {id:3, name:"not to be deleted"}];
var idsToDelete = [1, 2];
var res = arr.map((i, idx)=>{
return arr[idx] = idsToDelete.includes(i.id)? undefined : arr[idx]
}).filter(i=>i)
console.log(res)
You can try Lodash.js functions _.forEach() and _.remove()
let valuesArr = [
{id: 1, name: "dog"},
{id: 2, name: "cat"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
{id: 5, name: "pig"},
];
let removeValFromIndex = [
{id: 2, name: "cat"},
{id: 5, name: "pig"},
];
_.forEach(removeValFromIndex, (indi) => {
_.remove(valuesArr, (item) => {
return item.id === indi.id;
});
})
console.log(valuesArr)
/*[
{id: 1, name: "dog"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
]; */
Don't forget to clone (_.clone(valuesArr) or [...valuesArr]) before mutate your array

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 string from array using angularjs or javascript

var array = [
{id: 1, text: "one"},
{id: 2, text: "two"},
{id: 3, text: "three"},
{id: 4, text: "four"},
{id: 5, text: "five"}
];
var name = array.find(function(item){
return item.id == $localStorage.id;
});
returns me {id: 2, text: "two"}
expected two only string nothing else should print
You can first find the object and then get the text property by checking if the find() operation actually returned a object or it is undefined.
var array = [{
id: 1,
text: "one"
},
{
id: 2,
text: "two"
},
{
id: 3,
text: "three"
},
{
id: 4,
text: "four"
},
{
id: 5,
text: "five"
}
];
var findObj = array.find(function(item) {
return item.id == 2;
});
//check if findObj is defined or not
var name = findObj? findObj.text: null;
console.log(name);
You can also use destructuring to get that text value directly from find() if you are sure the object exist for that localStorage value. Otherwise, it will raise error.
var array = [{
id: 1,
text: "one"
},
{
id: 2,
text: "two"
},
{
id: 3,
text: "three"
},
{
id: 4,
text: "four"
},
{
id: 5,
text: "five"
}
];
var {text} = array.find(function(item) {
return item.id == 2;
});
console.log(text);
What you did returns the element at the position where item.id == $localStorage.id. If you want to get the text, then after the element is returned in var name, you just do name.text because array.find() returns the element that passed the logical operation.
You can use filter and map. This way you can customize your filtered result the way you want.
var array = [
{id: 1, text: "one"},
{id: 2, text: "two"},
{id: 3, text: "three"},
{id: 4, text: "four"},
{id: 5, text: "five"}
];
var name = array.filter(a=> a.id === 2).map(b=> {return b.text});
console.log(name)
You should retrieve property text of found object:
var object = array.find(function(item){
return item.id === $localStorage.id;
});
var name = object.text;
If you like to use es6 syntax, you can write like this.
You did everything good except, you needed to get specific object value.
const array = [
{ id: 1, text: "one" },
{ id: 2, text: "two" },
{ id: 3, text: "three" },
{ id: 4, text: "four" },
{ id: 5, text: "five" }
];
// So here i use same find as you did.
let object = array.find(item => {
return item.id == $localStorage.id;
});
// And assigning text property of object to variable 'name'
// since object, can be undefined, using OR empty object,
// so no error will be thrown if so.
let { text: name } = object || {};
console.log(name);
from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find:
The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
Try like this way to get text attribute value while using find by id
var array = [{
id: 1,
text: "one"
},
{
id: 2,
text: "two"
},
{
id: 3,
text: "three"
},
{
id: 4,
text: "four"
},
{
id: 5,
text: "five"
}
];
var name = array.find(function(item) {
return item.id == 2;
}).text;
console.log(name);
find will return the object that satisfy the condition
var object = array.find(function(item) {
return item.id == $localStorage.id;
});
var name = object? object.text: null;
console.log(name);

Lodash check if any object in array contains id match from another array

I have one user array like:
var users = [{
id: 1,
name: 'ABC',
isDisplay: true
}, {
id: 2,
name: 'XYZ',
isDisplay: true
}, {
id: 3,
name: 'JKL',
isDisplay: true
}];
And another array selectedUsers which contains some object from above array like:
var selectedUsers = [{
id: 1,
name: 'ABC'
},
{
id: 3,
name: 'JKL'
}];
Not with lodash, i want to indentify which object are present in second array with matching its ID.
_.each(users, (_u) => {
if(selectedUsers.includes(_u)) {
_u.isDisplay = false;
} else {
_u.isDisplay = true;
}
});
I have tried to match whole object with includes but it dint work, because i am using angularjs, so angular put some $$hashkey with object, so it will not match, Is there any other way to do this.
var users = [{
id: 1,
name: 'ABC',
isDisplay: true
}, {
id: 2,
name: 'XYZ',
isDisplay: true
}, {
id: 3,
name: 'JKL',
isDisplay: true
}];
var selectedUsers = [{
id: 1,
name: 'ABC'
},
{
id: 3,
name: 'JKL'
}];
var intersection = _.intersectionBy(users, selectedUsers, 'id');
console.log(intersection);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
Create a Set of selected ids (selectedUsersIds). Iterate the users array with Array#forEach, assign the value of isDisplay by checking if the id exists in the selectedUsersIds set:
const users = [{"id":1,"name":"ABC","isDisplay":true},{"id":2,"name":"XYZ","isDisplay":true},{"id":3,"name":"JKL","isDisplay":true}];
const selectedUsers = [{"id":1,"name":"ABC"},{"id":3,"name":"JKL"}];
const selectedUsersIds = new Set(selectedUsers.map(({ id }) => id));
users.forEach((u) => u.isDisplay = selectedUsersIds.has(u.id));
console.log(users);

How union arrays with validate only one property

Joining of Arrays.
I'm in need of running a "Join Array" objects, but, I need duplicated objects to be removed, see:
Example
var objArray1 = [
{ Id: 1, Name: 'João', Order: 2 },
{ Id: 2, Name: 'Pedro', Order: 5 }
];
var objArray2 = [
{ Id: 2, Name: 'Pedro', Order: 6 },
{ Id: 3, Name: 'Manoel', Order: 9 }
];
Actual code:
var result = _.union(objArray1,objArray2);
=> [
{ Id: 1, Name: 'João', Order: 2 },
{ Id: 2, Name: 'Pedro', Order: 5 },
{ Id: 2, Name: 'Pedro', Order: 6 },
{ Id: 3, Name: 'Manoel', Order: 9 }
];
I need this result:
[
{ Id: 1, Name: 'João', Order: 2 },
{ Id: 2, Name: 'Pedro', Order: 5 },
{ Id: 3, Name: 'Manoel', Order: 9 }
];
Basic I need join arrays with filter the one property, I need is possible with For but I would like a better solution
use underscore unique function as follows
var result = _.uniq(_.union(objArray1, objArray2), false, function(item){ return item.Id; });
not 100% sure if the false should be true
or, as seems to be a trend on SO - the sexy ES2015 version
var result = _.uniq(_.union(objArray1, objArray2), false, item => item.Id);

Categories

Resources