Removing duplicates in a array object - javascript

I have an array object as follows:
details :
Array[2]
>0: Object
Name:"a"
Desc:"Desc"
>1: Object
Name:"b"
Desc:"Desc2"
>2: Object
Name:"C"
Desc:"Desc"
I want to remove the last object since the "Desc" has the duplicate entry with the first entry.
I tried this approach in javascript,
removedup = details.reduce(function(a,b) { if (a.indexOf(b) < 0) a.push(b); return a },[]);
I want the output, to remove the duplicates and therefore adjust the array size.
details :
Array[1]
>0: Object
Name:"a"
Desc:"Desc"
>1: Object
Name:"b"
Desc:"Desc2"
what can I modify in logic?

You could use Array#filter() and thisArgs for a temporary object.
var details = [{ Name: 'a', desc: 'Desc' }, { Name: 'b', desc: 'Desc2' }, { Name: 'C', desc: 'Desc' }, {Name: 'a', desc: 'toString'}],
removedup = details.filter(function (a) {
if (!(a.desc in this)) {
this[a.desc] = true;
return true;
}
}, Object.create(null));
document.write('<pre> ' + JSON.stringify(removedup, 0, 4) + '</pre>');

Try this:
var modified = details.filter(function (item) {
return !details.some(function (item_) {
return item_ !== item && item_.Desc === item.Desc;
});
});

Using loadash
var output = _.chain(Array).reverse().indexBy('Desc').toArray().value();

Related

React - Filter JSON array if key exists [duplicate]

I have an array of objects and I'm wondering the best way to search it. Given the below example how can I search for name = "Joe" and age < 30? Is there anything jQuery can help with or do I have to brute force this search myself?
var names = new Array();
var object = { name : "Joe", age:20, email: "joe#hotmail.com"};
names.push(object);
object = { name : "Mike", age:50, email: "mike#hotmail.com"};
names.push(object);
object = { name : "Joe", age:45, email: "mike#hotmail.com"};
names.push(object);
A modern solution with Array.prototype.filter():
const found_names = names.filter(v => v.name === "Joe" && v.age < 30);
Or if you still use jQuery, you may use jQuery.grep():
var found_names = $.grep(names, function(v) {
return v.name === "Joe" && v.age < 30;
});
You can do this very easily with the [].filter method:
var filterednames = names.filter(function(obj) {
return (obj.name === "Joe") && (obj.age < 30);
});
You can learn more about it on this MDN page.
You could utilize jQuery.filter() function to return elements from a subset of the matching elements.
var names = [
{ name : "Joe", age:20, email: "joe#hotmail.com"},
{ name : "Mike", age:50, email: "mike#hotmail.com"},
{ name : "Joe", age:45, email: "mike#hotmail.com"}
];
var filteredNames = $(names).filter(function( idx ) {
return names[idx].name === "Joe" && names[idx].age < 30;
});
$(filteredNames).each(function(){
$('#output').append(this.name);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"/>
var nameList = [
{name:'x', age:20, email:'x#email.com'},
{name:'y', age:60, email:'y#email.com'},
{name:'Joe', age:22, email:'joe#email.com'},
{name:'Abc', age:40, email:'abc#email.com'}
];
var filteredValue = nameList.filter(function (item) {
return item.name == "Joe" && item.age < 30;
});
//To See Output Result as Array
console.log(JSON.stringify(filteredValue));
You can simply use javascript :)
For those who want to filter from an array of objects using any key:
function filterItems(items, searchVal) {
return items.filter((item) => Object.values(item).includes(searchVal));
}
let data = [
{ "name": "apple", "type": "fruit", "id": 123234 },
{ "name": "cat", "type": "animal", "id": 98989 },
{ "name": "something", "type": "other", "id": 656565 }]
console.log("Filtered by name: ", filterItems(data, "apple"));
console.log("Filtered by type: ", filterItems(data, "animal"));
console.log("Filtered by id: ", filterItems(data, 656565));
filter from an array of the JSON objects:**
var names = [{
name: "Joe",
age: 20,
email: "joe#hotmail.com"
},
{
name: "Mike",
age: 50,
email: "mike#hotmail.com"
},
{
name: "Joe",
age: 45,
email: "mike#hotmail.com"
}
];
const res = _.filter(names, (name) => {
return name.name == "Joe" && name.age < 30;
});
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
So quick question. What if you have two arrays of objects and you would like to 'align' these object arrays so that you can make sure each array's objects are in the order as the other array's? What if you don't know what keys and values any of the objects inside of the arrays contains... Much less what order they're even in?
So you need a 'WildCard Expression' for your [].filter, [].map, etc. How do you get a wild card expression?
var jux = (function(){
'use strict';
function wildExp(obj){
var keysCrude = Object.keys(obj),
keysA = ('a["' + keysCrude.join('"], a["') + '"]').split(', '),
keysB = ('b["' + keysCrude.join('"], b["') + '"]').split(', '),
keys = [].concat(keysA, keysB)
.sort(function(a, b){ return a.substring(1, a.length) > b.substring(1, b.length); });
var exp = keys.join('').split(']b').join('] > b').split(']a').join('] || a');
return exp;
}
return {
sort: wildExp
};
})();
var sortKeys = {
k: 'v',
key: 'val',
n: 'p',
name: 'param'
};
var objArray = [
{
k: 'z',
key: 'g',
n: 'a',
name: 'b'
},
{
k: 'y',
key: 'h',
n: 'b',
name: 't'
},
{
k: 'x',
key: 'o',
n: 'a',
name: 'c'
}
];
var exp = jux.sort(sortKeys);
console.log('#juxSort Expression:', exp);
console.log('#juxSort:', objArray.sort(function(a, b){
return eval(exp);
}));
You can also use this function over an iteration for each object to create a better collective expression for all of the keys in each of your objects, and then filter your array that way.
This is a small snippet from the API Juxtapose which I have almost complete, which does this, object equality with exemptions, object unities, and array condensation. If these are things you need or want for your project please comment and I'll make the lib accessible sooner than later.
Hope this helps! Happy coding :)
The most straightforward and readable approach will be the usage of native javascript filter method.
Native javaScript filter takes a declarative approach in filtering array elements. Since it is a method defined on Array.prototype, it iterates on a provided array and invokes a callback on it. This callback, which acts as our filtering function, takes three parameters:
element — the current item in the array being iterated over
index — the index or location of the current element in the array that is being iterated over
array — the original array that the filter method was applied on
Let’s use this filter method in an example. Note that the filter can be applied on any sort of array. In this example, we are going to filter an array of objects based on an object property.
An example of filtering an array of objects based on object properties could look something like this:
// Please do not hate me for bashing on pizza and burgers.
// and FYI, I totally made up the healthMetric param :)
let foods = [
{ type: "pizza", healthMetric: 25 },
{ type: "burger", healthMetric: 10 },
{ type: "salad", healthMetric: 60 },
{ type: "apple", healthMetric: 82 }
];
let isHealthy = food => food.healthMetric >= 50;
const result = foods.filter(isHealthy);
console.log(result.map(food => food.type));
// Result: ['salad', 'apple']
To learn more about filtering arrays in functions and yo build your own filtering, check out this article:
https://medium.com/better-programming/build-your-own-filter-e88ba0dcbfae

How to check if array contains at least one object ?

I want to check if array contains object or not. I am not trying to compare values just want to check in my array if object is present or not?
Ex.
$arr = ['a','b','c'] // normal
$arr = [{ id: 1}, {id: 2}] // array of objects
$arr = [{id: 1}, {id:2}, 'a', 'b'] // mix values
So how can i check if array contains object
You can use some method which tests whether at least one element in the array passes the test implemented by the provided function.
let arr = [{id: 1}, {id:2}, 'a', 'b'];
let exists = arr.some(a => typeof a == 'object');
console.log(exists);
I want to check if array contains object or not
Use some to simply check if any item of the array has value of type "object"
var hasObject = $arr.some( function(val){
return typeof val == "object";
});
var hasObject = function(arr) {
for (var i=0; i<arr.length; i++) {
if (typeof arr[i] == 'object') {
return true;
}
}
return false;
};
console.log(hasObject(['a','b','c']));
console.log(hasObject([{ id: 1}, {id: 2}]));
console.log(hasObject([{id: 1}, {id:2}, 'a', 'b']));
You could count the objects and use it for one of the three types to return.
function getType(array) {
var count = array.reduce(function (r, a) {
return r + (typeof a === 'object');
}, 0);
return count === array.length
? 'array of objects'
: count
? 'mix values'
: 'normal';
}
console.log([
['a', 'b', 'c'],
[{ id: 1 }, { id: 2 }],
[{ id: 1 }, { id: 2 }, 'a', 'b']
].map(getType));
With a type check on array
const hasObject = a => Array.isArray(a) && a.some(val => typeof val === 'object')

TypeScript - Take object out of array based on attribute value

My array looks like this:
array = [object {id: 1, value: "itemname"}, object {id: 2, value: "itemname"}, ...]
all my objects have the same attibutes, but with different values.
Is there an easy way I can use a WHERE statement for that array?
Take the object where object.id = var
or do I just need to loop over the entire array and check every item? My array has over a 100 entries, so I wanted to know if there was a more efficient way
Use Array.find:
let array = [
{ id: 1, value: "itemname" },
{ id: 2, value: "itemname" }
];
let item1 = array.find(i => i.id === 1);
Array.find at MDN: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/find
I'd use filter or reduce:
let array = [
{ id: 1, value: "itemname" },
{ id: 2, value: "itemname" }
];
let item1 = array.filter(item => item.id === 1)[0];
let item2 = array.reduce((prev, current) => prev || current.id === 1 ? current : null);
console.log(item1); // Object {id: 1, value: "itemname"}
console.log(item2); // Object {id: 1, value: "itemname"}
(code in playground)
If you care about iterating over the entire array then use some:
let item;
array.some(i => {
if (i.id === 1) {
item = i;
return true;
}
return false;
});
(code in playground)
You can search a certain value in array of objects using TypeScript dynamically if you need to search the value from all fields of the object without specifying column
var searchText = 'first';
let items = [
{ id: 1, name: "first", grade: "A" },
{ id: 2, name: "second", grade: "B" }
];
This below code will search for the value
var result = items.filter(item =>
Object.keys(item).some(k => item[k] != null &&
item[k].toString().toLowerCase()
.includes(searchText.toLowerCase()))
);
Same approach can be used to make a Search Filter Pipe in angularjs 4 using TypeScript
I had to declare the type to get it to work in typescript:
let someId = 1
array.find((i: { id: string; }) => i.id === someId)
You'll have to loop over the array, but if you make a hashmap to link each id to an index and save that, you only have to do it once, so you can reference any objeft after that directly:
var idReference = myArray.reduce(function( map, record, index ) {
map[ record.id ] = index;
return map;
}, {});
var objectWithId5 = myArray[ idReference["5"] ];
This does assume all ids are unique though.

How to add non duplicate objects in an array in javascript?

I want to add non-duplicate objects into a new array.
var array = [
{
id: 1,
label: 'one'
},
{
id: 1,
label: 'one'
},
{
id: 2,
label: 'two'
}
];
var uniqueProducts = array.filter(function(elem, i, array) {
return array.indexOf(elem) === i;
});
console.log('uniqueProducts', uniqueProducts);
// output: [object, object, object]
live code
I like the class based approach using es6. The example uses lodash's _.isEqual method to determine equality of objects.
var array = [{
id: 1,
label: 'one'
}, {
id: 1,
label: 'one'
}, {
id: 2,
label: 'two'
}];
class UniqueArray extends Array {
constructor(array) {
super();
array.forEach(a => {
if (! this.find(v => _.isEqual(v, a))) this.push(a);
});
}
}
var unique = new UniqueArray(array);
console.log(unique);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
Usually, you use an object to keep track of your unique keys. Then, you convert the object to an array of all property values.
It's best to include a unique id-like property that you can use as an identifier. If you don't have one, you need to generate it yourself using JSON.stringify or a custom method. Stringifying your object will have a downside: the order of the keys does not have to be consistent.
You could create an objectsAreEqual method with support for deep comparison, but this will slow your function down immensely.
In two steps:
var array=[{id:1,label:"one"},{id:1,label:"one"},{id:2,label:"two"}];
// Create a string representation of your object
function getHash(obj) {
return Object.keys(obj)
.sort() // Keys don't have to be sorted, do it manually here
.map(function(k) {
return k + "_" + obj[k]; // Prefix key name so {a: 1} != {b: 1}
})
.join("_"); // separate key-value-pairs by a _
}
function getHashBetterSolution(obj) {
return obj.id; // Include unique ID in object and use that
};
// When using `getHashBetterSolution`:
// { '1': { id: '1', label: 'one' }, '2': /*etc.*/ }
var uniquesObj = array.reduce(function(res, cur) {
res[getHash(cur)] = cur;
return res;
}, {});
// Convert back to array by looping over all keys
var uniquesArr = Object.keys(uniquesObj).map(function(k) {
return uniquesObj[k];
});
console.log(uniquesArr);
// To show the hashes
console.log(uniquesObj);
You can use Object.keys() and map() to create key for each object and filter to remove duplicates.
var array = [{
id: 1,
label: 'one'
}, {
id: 1,
label: 'one'
}, {
id: 2,
label: 'two'
}];
var result = array.filter(function(e) {
var key = Object.keys(e).map(k => e[k]).join('|');
if (!this[key]) {
this[key] = true;
return true;
}
}, {});
console.log(result)
You could use a hash table and store the found id.
var array = [{ id: 1, label: 'one' }, { id: 1, label: 'one' }, { id: 2, label: 'two' }],
uniqueProducts = array.filter(function(elem) {
return !this[elem.id] && (this[elem.id] = true);
}, Object.create(null));
console.log('uniqueProducts', uniqueProducts);
Check with all properties
var array = [{ id: 1, label: 'one' }, { id: 1, label: 'one' }, { id: 2, label: 'two' }],
keys = Object.keys(array[0]), // get the keys first in a fixed order
uniqueProducts = array.filter(function(a) {
var key = keys.map(function (k) { return a[k]; }).join('|');
return !this[key] && (this[key] = true);
}, Object.create(null));
console.log('uniqueProducts', uniqueProducts);
You can use reduce to extract out the unique array and the unique ids like this:
var array=[{id:1,label:"one"},{id:1,label:"one"},{id:2,label:"two"}];
var result = array.reduce(function(prev, curr) {
if(prev.ids.indexOf(curr.id) === -1) {
prev.array.push(curr);
prev.ids.push(curr.id);
}
return prev;
}, {array: [], ids: []});
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}
If you don't know the keys, you can do this - create a unique key that would help you identify duplicates - so I did this:
concat the list of keys and values of the objects
Now sort them for the unique key like 1|id|label|one
This handles situations when the object properties are not in order:
var array=[{id:1,label:"one"},{id:1,label:"one"},{id:2,label:"two"}];
var result = array.reduce(function(prev, curr) {
var tracker = Object.keys(curr).concat(Object.keys(curr).map(key => curr[key])).sort().join('|');
if(!prev.tracker[tracker]) {
prev.array.push(curr);
prev.tracker[tracker] = true;
}
return prev;
}, {array: [], tracker: {}});
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}

How can I get a unique array based on object property using underscore

I have an array of objects and I want to get a new array from it that is unique based only on a single property, is there a simple way to achieve this?
Eg.
[ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
Would result in 2 objects with name = bill removed once.
Use the uniq function
var destArray = _.uniq(sourceArray, function(x){
return x.name;
});
or single-line version
var destArray = _.uniq(sourceArray, x => x.name);
From the docs:
Produces a duplicate-free version of the array, using === to test object equality. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iterator function.
In the above example, the function uses the objects name in order to determine uniqueness.
If you prefer to do things yourself without Lodash, and without getting verbose, try this uniq filter with optional uniq by property:
const uniqFilterAccordingToProp = function (prop) {
if (prop)
return (ele, i, arr) => arr.map(ele => ele[prop]).indexOf(ele[prop]) === i
else
return (ele, i, arr) => arr.indexOf(ele) === i
}
Then, use it like this:
const obj = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
obj.filter(uniqFilterAccordingToProp('abc'))
Or for plain arrays, just omit the parameter, while remembering to invoke:
[1,1,2].filter(uniqFilterAccordingToProp())
If you want to check all the properties then
lodash 4 comes with _.uniqWith(sourceArray, _.isEqual)
A better and quick approach
var table = [
{
a:1,
b:2
},
{
a:2,
b:3
},
{
a:1,
b:4
}
];
let result = [...new Set(table.map(item => item.a))];
document.write(JSON.stringify(result));
Found here
You can use the _.uniqBy function
var array = [ { id: 1, name: 'bob' }, { id: 2, name: 'bill' }, { id: 1, name: 'bill' },{ id: 2, name: 'bill' } ];
var filteredArray = _.uniqBy(array,function(x){ return x.id && x.name;});
console.log(filteredArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
In the above example, filtering is based on the uniqueness of combination of properties id & name.
if you have multiple properties for an object.
then to find unique array of objects based on specific properties, you could follow this method of combining properties inside _.uniqBy() method.
I was looking for a solution which didn't require a library, and put this together, so I thought I'd add it here. It may not be ideal, or working in all situations, but it's doing what I require, so could potentially help someone else:
const uniqueBy = (items, reducer, dupeCheck = [], currentResults = []) => {
if (!items || items.length === 0) return currentResults;
const thisValue = reducer(items[0]);
const resultsToPass = dupeCheck.indexOf(thisValue) === -1 ?
[...currentResults, items[0]] : currentResults;
return uniqueBy(
items.slice(1),
reducer,
[...dupeCheck, thisValue],
resultsToPass,
);
}
const testData = [
{text: 'hello', image: 'yes'},
{text: 'he'},
{text: 'hello'},
{text: 'hell'},
{text: 'hello'},
{text: 'hellop'},
];
const results = uniqueBy(
testData,
item => {
return item.text
},
)
console.dir(results)
In case you need pure JavaScript solution:
var uniqueProperties = {};
var notUniqueArray = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ];
for(var object in notUniqueArray){
uniqueProperties[notUniqueArray[object]['name']] = notUniqueArray[object]['id'];
}
var uniqiueArray = [];
for(var uniqueName in uniqueProperties){
uniqiueArray.push(
{id:uniqueProperties[uniqueName],name:uniqueName});
}
//uniqiueArray
unique array by id property with ES6:
arr.filter((a, i) => arr.findIndex(b => b.id === a.id) === i); // unique by id
replace b.id === a.id with the relevant comparison for your case

Categories

Resources