Filtering JSON Array - javascript

Any guidance or reference is appreciated.
Using javascript's (map reduce and filter), I am trying to get a collection of all available rooms across multiple vendors in the given JSON array. The logic for this :
**User Input **: checkIn Date, checkOut Date and Property Name
**Filter Logic **
Check is the item availableFrom and availableTo dates fall in the range of checkIn and checkOut.
Check if the item propertyName matches the user input
Iterate through the items to get the common rooms
I have a JSON structure is :
var callOutResult =
[
{
"vendorId": "1",
"vendorName": "ABC",
"vendorPropertyId": "100",
"propertyName": "Some Name",
"availableFrom": "2012-04-01T15:00:00.001Z",
"availableTo": "2012-04-25T12:00:00.001Z",
"available": {
"floor1": ["101","105","106"],
"floor2": ["202","204","208"],
"floor3": ["301","304","307"],
"floor4": ["405","409","410"],
"floor5": ["502","504","506"],
"floor6": ["602","607","609"]
}
},
{
"vendorId": "2",
"vendorName": "XYZ",
"vendorPropertyId": "300",
"propertyName": "Some Name",
"availableFrom": "2012-04-10T15:00:00.001Z",
"availableTo": "2012-05-20T12:00:00.001Z",
"available": {
"floor1": ["104","106","107"],
"floor2": ["208","214"]
}
},
{
"vendorId": "3",
"vendorName": "PQR",
"vendorPropertyId": "450",
"propertyName": "Some Name",
"availableFrom": "2012-01-23T15:00:00.001Z",
"availableTo": "2012-06-25T12:00:00.001Z",
"available": {
"floor1": ["101","102","103"],
"floor2": ["208","212"],
"floor3": ["302","306","315"],
"floor4": ["415","409","420"]
}
}
]
Code I have thus far
var checkInDate = new Date("2012-04-10");
var checkOutDate = new Date("2012-04-22");
var propertyName = 'Some Name'
// Check in & Check Out Date Filter
var filter1 = callOutResult.filter(function (arrayItem) {return arrayItem.availableFrom <= checkOutDate && arrayItem.availableTo >= checkInDate});
// Property Name Filter
var filter2 = filter1.filter(function (arrayItem) {return arrayItem.propertyName === propertyName});
result = Object
.values(filter2)
.reduce(function(a, b){
// CANNOT FIGURE OUT THE LOGIC TO ITERATE THROUGH THE rooms.
});
My goal is to filter the array to find available rooms. Reference to article, other sample code, anything that will guide me.

If you were trying to find the room(s) that fall within the specified checkin and checkout dates, have the required propertyName and are found in all the matched items, then the following might be helpful:
var callOutResult =
[
{
"vendorId": "1",
"vendorName": "ABC",
"vendorPropertyId": "100",
"propertyName": "Some Name",
"availableFrom": "2012-04-01T15:00:00.001Z",
"availableTo": "2012-04-25T12:00:00.001Z",
"available": {
"floor1": ["101","105","106"],
"floor2": ["202","204","208"],
"floor3": ["301","304","307"],
"floor4": ["405","409","410"],
"floor5": ["502","504","506"],
"floor6": ["602","607","609"]
}
},
{
"vendorId": "2",
"vendorName": "XYZ",
"vendorPropertyId": "300",
"propertyName": "Some Name",
"availableFrom": "2012-04-10T15:00:00.001Z",
"availableTo": "2012-05-20T12:00:00.001Z",
"available": {
"floor1": ["104","106","107"],
"floor2": ["208","214"]
}
},
{
"vendorId": "3",
"vendorName": "PQR",
"vendorPropertyId": "450",
"propertyName": "Some Name",
"availableFrom": "2012-01-23T15:00:00.001Z",
"availableTo": "2012-06-25T12:00:00.001Z",
"available": {
"floor1": ["101","102","103"],
"floor2": ["208","212"],
"floor3": ["302","306","315"],
"floor4": ["415","409","420"]
}
}
];
// convert date strings into Date objects:
callOutResult.forEach(e=>["From","To"].forEach(ft=>e["available"+ft]=new Date(e["available"+ft])));
var checkInDate = new Date("2012-04-10T15:10:00.001Z");
var checkOutDate = new Date("2012-04-22T09:00:00.001Z");
var propertyName = 'Some Name';
// check in & check out date and propertyName filter:
var filter = callOutResult.filter(function(itm) {
return itm.availableFrom <= checkInDate && itm.availableTo >= checkOutDate && itm.propertyName === propertyName});
// check the existence of the room(s) for all matched vendors:
console.log(filter.map(e=>Object.values(e.available).flat(2)) // flatten rooms for each vendor
.reduce((a,c)=>{return a.filter(e=>c.some(f=>e==f))})) // a room must occur in each vendor object!
If the result should contain only those rooms (on their individual floors) that
fulfil both timing and
propertyName conditions
and are only listed once,
then the following might be helpful:
var callOutResult = [{"vendorId": "1","vendorName": "ABC","vendorPropertyId": "100","propertyName": "Some Name","availableFrom": "2012-04-01T15:00:00.001Z","availableTo": "2012-04-25T12:00:00.001Z","available": {"floor1": ["101", "105", "106"],"floor2": ["202", "204", "208"],"floor3": ["301", "304", "307"],"floor4": ["405", "409", "410"],"floor5": ["502", "504", "506"],"floor6": ["602", "607", "609"]}},{"vendorId": "2","vendorName": "XYZ","vendorPropertyId": "300","propertyName": "Some Name","availableFrom": "2012-04-10T15:00:00.001Z","availableTo": "2012-05-20T12:00:00.001Z","available": {"floor1": ["104", "106", "107"],"floor2": ["208", "214"]}},{"vendorId": "3","vendorName": "PQR","vendorPropertyId": "450","propertyName": "Some Name","availableFrom": "2012-01-23T15:00:00.001Z","availableTo": "2012-06-25T12:00:00.001Z","available": {"floor1": ["101", "102", "103"],"floor2": ["208", "212"],"floor3": ["302", "306", "315"],"floor4": ["415", "409", "420"]}}];
// convert date strings into Date objects:
callOutResult.forEach(e => ["From", "To"].forEach(ft => e["available" + ft] = new Date(e["available" + ft])));
var checkInDate = new Date("2012-04-10T15:10:00.001Z");
var checkOutDate = new Date("2012-04-22T09:00:00.001Z");
var propertyName = 'Some Name';
// check in & check out date and propertyName filter:
var dateProp = callOutResult.filter(function(itm) {
return itm.availableFrom <= checkInDate && itm.availableTo >= checkOutDate && itm.propertyName === propertyName
});
const res = Object.entries(dateProp.reduce((a, e) => {
Object.entries(e.available).forEach(([fl, rms]) => {
let afl = a[fl] ??= {};
rms.forEach(r => afl[r] = afl[r] ? afl[r] + 1 : 1);
});
return a;
}, {})).map(([fl, rms]) => Object.fromEntries([
[fl, Object.entries(rms).filter(([r, cnt]) => cnt == 1).map(([r]) => r)]
]));
console.log(JSON.stringify(res));

Related

Trying to filter an array of objects based on several fields in JS [duplicate]

This question already has answers here:
Filter array of objects by multiple properties and values
(4 answers)
Closed 1 year ago.
First of all, my apologies if my question is too obvious but I my knowledge is limited and I don't get how to achieve what I am trying. I have a JSON file as source of the data (songs) and I am trying to filter that data based on several fields (level, name, artist, etc.).
Example of some data from the JSON:
[
{"artist": "Black",
"categories": "Arreglos",
"date": 1639127185000,
"level": "Fácil",
"musicStyle": "Pop/Rock",
"name": "Wonderful Life",
"practice": "n/a",
"preloadID": "Wonderful_Life",
"subtitle": "Fácil",
},
{"artist": "",
"categories": "Arreglos",
"date": 1587948049309,
"image": "./images/arreglos/a_million_dreams.jpeg",
"level": "Fácil",
"musicStyle": "Film/TV",
"name": "A million dreams",
"preloadID": "AMillionDreams_Facil",
"subtitle": "Fácil",
},
{"artist": "",
"categories": "Arreglos",
"date": 1587948046688,
"image": "./images/arreglos/a_million_dreams.jpeg",
"level": "Principiante",
"musicStyle": "Film/TV",
"name": "A million dreams",
"preloadID": "AMillionDreams_Principiante",
"subtitle": "Principiante",
},
{"artist": "Vanessa Carlton",
"categories": "Arreglos",
"date": 1602939064030,
"level": "Fácil",
"musicStyle": "Pop/Rock",
"name": "A thousand miles",
"preloadID": "AThousandMiles_Facil",
"subtitle": "Fácil",
},
{"artist": "Vanessa Carlton",
"categories": "Arreglos",
"date": 1602939064033,
"level": "Muy fácil",
"musicStyle": "Pop/Rock",
"name": "A thousand miles",
"preloadID": "AThousandMiles_MuyFacil",
"subtitle": "Muy fácil",
"tonality": ""
},
]
And this is the script I have to try to filter the data.
let filteredItems = [];
let filterLevel=this.context.appActions.dataSlots['ds_LevelFilter'];
let filterStr=this.context.appActions.dataSlots['ds_SearchFilter'];
filterStr=filterStr.toLowerCase();
items.forEach(item => {
if (item["artist"].toLowerCase().includes(filterStr) || item["name"].toLowerCase().includes(filterStr) ) {
filteredItems.push(item);
}
});
items.forEach(item => {
if (item["level"] == filterLevel) {
filteredItems.push(item);
}
});
items = filteredItems.sort((a, b) => {
return new Date(b.date) - new Date(a.date);
}).slice(0,this.context.appActions.dataSlots['ds_limitQuery']);
return items;
For filterStr, I have a text field where the user would write a search and if that is included in name or artist, it should return the resulted documents.
In filterLevel I have a picker with several values (Easy, Medium, etc. in Spanish) and it should be equal to the field "level" from the data.
I am not sure if the code shows what I am trying but if I use just the first if block (name and artist) it works perfectly. But if I add the second, it gives me an error of duplicated keys (it is a React project). I am guessing the script is not correct.
Use an Object filter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
const songs = [
{
id: 1,
name: 'Golden Hour',
artist: 'Kacey Musgraves',
level: "Fácil",
},
{
id: 2,
name: 'King Size Manger',
artist: 'Josh Turner',
level: "Fácil",
},
{
id: 3,
name: 'Legend',
artist: 'Bob Marley',
level: "Muy fácil",
},
{
id: 4,
name: 'Catch A Fire',
artist: 'Bob Marley',
level: "Muy fácil",
},
{
id: 5,
name: 'Fine Line',
artist: 'Harry Styles',
level: "Fácil",
},
]
function filterSongs(filterStr = '', filterLevel = '') {
return songs.filter(item => {
const context = filterStr.toLowerCase()
// Filter on level else ignore by always returning true.
let result = filterLevel.length ? (item.level === filterLevel) : true
// If result is false because level was set and did not match then skip filterStr check.
// If result is true because level was ignored or matched then search if filterStr has value.
if(result && filterStr.length) {
result = item.artist.toLowerCase().includes(context) || item.name.toLowerCase().includes(context)
}
return result
})
}
console.log('Search for Harry', filterSongs('Harry'))
console.log('Search for level Fácil', filterSongs('', 'Fácil'))
console.log('Search for Golden with level Fácil', filterSongs('Golden', 'Fácil'))
console.log('Search for Bob', filterSongs('Bob'))
How to implement the above code with your example:
let filterLevel = this.context.appActions.dataSlots['ds_LevelFilter'] ?? '';
let filterStr = this.context.appActions.dataSlots['ds_SearchFilter'] ?? '';
let filterLimit = this.context.appActions.dataSlots['ds_limitQuery'] ?? 15;
function filterSongs(filterStr = '', filterLevel = '') {
return songs.filter(item => {
const context = filterStr.toLowerCase()
// Filter on level else ignore by always returning true.
let result = filterLevel.length ? (item.level === filterLevel) : true
// If result is false because level was set and did not match then skip filterStr check.
// If result is true because level was ignored or matched then search if filterStr has value.
if(result && filterStr.length) {
result = item.artist.toLowerCase().includes(context) || item.name.toLowerCase().includes(context)
}
return result
})
}
let filteredItems = filterSongs(filterStr, filterLevel)
return filteredItems.sort((a, b) => {
return new Date(b.date) - new Date(a.date);
}).slice(0,filterLimit);

simplify the nested condition for loop in javascript

I have my current ugly code to filter an array with specific requirements, is there any better ways to simplify the code by using arrow function or such in order to beautify and shorten the code? tks.
const NewTraitSet = [
{
"ValueSet": [
{
"Units": null,
"Type": "description A",
"Value": "description A"
},
{
"Units": null,
"Type": "description B",
"Value": "description B"
},
{
"Units": null,
"Type": "risk category",
"Value": "Decreased Risk"
}
],
"TraitInterpretation": "TraitInterpretation",
"TraitCategory": "Health"
},{
"ValueSet": [
{
"Units": null,
"Type": "description A",
"Value": "description A"
},
{
"Units": null,
"Type": "description B",
"Value": "description B"
},
{
"Units": null,
"Type": "risk category",
"Value": "Increased Risk"
}
],
"TraitInterpretation": "TraitInterpretation",
"TraitCategory": "DD Health",
}
]
const result = []
function fun(item, index) {
for (var key in item) {
if (key == "ValueSet") {
for (var obj in item[key]) {
if (item[key][obj]["Type"] == "risk category" && item[key][obj]["Value"] == "Decreased Risk") {
result.push(item)
}
}
}
}
return result
}
NewTraitSet.forEach(fun)
// sort traits by name
result.sort((a, b) => (a.TraitCategory > b.TraitCategory ? 1 : -1))
console.log(result)
I'm pretty new to javascript and not so sure how to use arrow function in my case, some advices will be brilliant. Or if there is better solution to get the same result, I will be more than happy to learn from it, tks.
Because your output array is composed of elements of your input array, use .filter. Since you're also only concerned with the ValueSet key, you only need to check that key, you don't need to iterate over all of an object's keys.
Then, you need to check if any of the elements in the array passes a test, and if so, push the whole object. The right method to perform such a test is .some:
const NewTraitSet=[{ValueSet:[{Units:null,Type:"description A",Value:"description A"},{Units:null,Type:"description B",Value:"description B"},{Units:null,Type:"risk category",Value:"Decreased Risk"}],TraitInterpretation:"TraitInterpretation",TraitCategory:"Health"},{ValueSet:[{Units:null,Type:"description A",Value:"description A"},{Units:null,Type:"description B",Value:"description B"},{Units:null,Type:"risk category",Value:"Increased Risk"}],TraitInterpretation:"TraitInterpretation",TraitCategory:"DD Health"}];
const result = NewTraitSet.filter(item => item.ValueSet.some(
({ Type, Value }) => Type === 'risk category' && Value === 'Decreased Risk'
));
console.log(result);
Or, if you're not comfortable with destructuring:
const NewTraitSet=[{ValueSet:[{Units:null,Type:"description A",Value:"description A"},{Units:null,Type:"description B",Value:"description B"},{Units:null,Type:"risk category",Value:"Decreased Risk"}],TraitInterpretation:"TraitInterpretation",TraitCategory:"Health"},{ValueSet:[{Units:null,Type:"description A",Value:"description A"},{Units:null,Type:"description B",Value:"description B"},{Units:null,Type:"risk category",Value:"Increased Risk"}],TraitInterpretation:"TraitInterpretation",TraitCategory:"DD Health"}];
const result = NewTraitSet.filter(item => item.ValueSet.some(
inner => inner.Type === 'risk category' && inner.Value === 'Decreased Risk'
));
console.log(result);
I used your code with some annotations.
const
newTraitSet = [{ ValueSet: [{ Units: null, Type: "description A", Value: "description A" }, { Units: null, Type: "description B", Value: "description B" }, { Units: null, Type: "risk category", Value: "Decreased Risk" }], TraitInterpretation: "TraitInterpretation", TraitCategory: "Health" }, { ValueSet: [{ Units: null, Type: "description A", Value: "description A" }, { Units: null, Type: "description B", Value: "description B" }, { Units: null, Type: "risk category", Value: "Increased Risk" }], TraitInterpretation: "TraitInterpretation", TraitCategory: "DD Health" }],
result = [];
function fun(item) { // remove unused variables
//for (var key in item) { // remove this, because you need only a single property
if (!("ValueSet" in item)) return; // return early, if "ValueSet" not exists in rhe object
// if (key == "ValueSet") {// remove check, because no iteration over the keys
for (let obj of item.ValueSet) { // use `of` for the values and key directly
if (obj.Type == "risk category" && obj.Value == "Decreased Risk") { // dot notation for known property
result.push(item);
}
}
//}
//}
// return result; // makes no sense in `forEach`. the return value is never used
}
newTraitSet.forEach(fun);
result.sort((a, b) => a.TraitCategory.localeCompare(b.TraitCategory ? 1 : -1)); // sort by strings
console.log(result);

Calculate object property values based on user id

Got an object containing a user id for each user and prices, would like to create a new object/array for each user (no duplicates) and be able to calculate the total sum of price for each user. Tried using Object.values() with map and filter but can't get it to work properly
{
"data": {
"item1": {
"price": "20",
"user": "user1"
},
"item2": {
"price": "10",
"user": "user2"
},
"item3": {
"price": "50",
"user": "user1"
}
}
}
Output something like this:
{
"users": {
"user1": {
"totalSum": "70",
},
"user2": {
"totalSum": "10",
}
}
}
I'm thinking about using map to present the "users"-data, maybe an array would be better?
Using function reduce.
Important: The attribute price is a String, this approach uses object Number to convert that value to a numeric one.
var obj = { "data": { "item1": { "price": "20", "user": "user1" }, "item2": { "price": "10", "user": "user2" }, "item3": { "price": "50", "user": "user1" } }};
var result = Object.keys(obj.data).reduce((a, k) => {
if (a.users[obj.data[k].user]) {
a.users[obj.data[k].user].totalSum += Number(obj.data[k].price);
} else {
a.users[obj.data[k].user] = {
"totalSum": Number(obj.data[k].price)
}
}
return a;
}, {
'users': {}
});
console.log(result);
.as-console-wrapper {
max-height: 100% !important; top: 0;
}
You could leverage ```reduce, more information here
code (haven't tried this)
var data = JSON.parse(mainObj).data;
var usersWithTotalExpenditure = Object.keys(data).reduce(function(result, key) {
var currentItem = data[key];
var useName = currentItem.user;
var price = Number(currentItem.price);
if (userName in result) {
result[userName].totalSum += price;
} else {
result[userName] = {
totalSum: price
};
}
return result;
}, {});
var resultObject = {
users: usersWithTotalExpenditure
}
You can use a forEach loop. This relies on Javascripts powerful OR operator, which coerces the first half of the expression to false if the current user's price is not defined (meaning it is a user the loop hasn't encountered before)
`c is your initial object's data, output is empty object`
const c = obj.data;
var output = {};
Object.keys(c).forEach((val) => {
output[c[val]["user"]] = parseInt(output[c[val]["user"]]) + parseInt(c[val]["price"]) || parseInt(c[val]["price"]);
})

Lower casing the keys in JSON - Node JS

I want to change a json array keys names from upper case letters to a lower case keys as the following
[
{
"_id": "581f2749fb9b6f22308f5063",
"WorkshopId": "1",
"WorkshopTitle": "workshop1",
"WorkshopPrice": "200",
"WorkshopDescription": "workshop1 is a test workshop",
"FloorNumber": "1",
"RoomNumber": "205",
"WorkshopLanguage": "english language",
"LastOnlineRegistrationDate": "15/10/2016",
"WorkshopDate": "1/11/2016",
"WorkshopStartTime": "8:00 AM",
"WorkshopEndTime": "11:00 AM",
"WorkshopRules": "Rules will be mentioned here",
"WorkshopCapacity": "200",
"Speaker": {
"SpeakerName": "John doe",
"AboutSpeaker": "About the speaker"
}
},
{
"_id": "581f27e796915434f44cd678",
"WorkshopId": "2",
"WorkshopTitle": "workshop2",
"WorkshopPrice": "200",
"WorkshopDescription": "workshop2 is a test workshop",
"FloorNumber": "1",
"RoomNumber": "205",
"WorkshopLanguage": "english language",
"LastOnlineRegistrationDate": "15/10/2016",
"WorkshopDate": "1/11/2016",
"WorkshopStartTime": "11:00 AM",
"WorkshopEndTime": "02:00 PM",
"WorkshopRules": "Rules will be mentioned here",
"WorkshopCapacity": "200",
"Speaker": {
"SpeakerName": "Jane doe",
"AboutSpeaker": "Jane doe - About the speaker"
}
}
]
for example WorkshopId must be changed to workshopid, I have a function in node js that query a collection in mongodb and return the json :
getWorkshops: function (db, response) {
db.collection('Workshops').find().toArray(function (err, results) {
var convertedArr = [];
//convert the json.
response.send(JSON.stringify(convertedArr));
});
any help?
This will map an object's keys to lowercase:
var upperCased = [
{ ID: 1, NAME: 'Fred' },
{ ID: 2, NAME: 'Sarah' },
{ ID: 3, NAME: 'Joe' },
];
var lowerCased = upperCased.map(function(item) {
var mapped = {};
for (var key in item) {
mapped[key.toLowerCase()] = item[key];
}
return mapped;
});
https://jsfiddle.net/5ouebw4b/2/
You could to it with a custom toJSON() function:
getWorkshops: function (db, response) {
db.collection('Workshops').find().toArray(function (err, results) {
results.toJSON = function () {
var newArr = [];
for (var obj in this) {
if (!this.hasOwnProperty(obj) || 'toJSON' === obj) continue;
var newObj = {};
for (var prop in this[obj]) {
if (!this[obj].hasOwnProperty(prop)) continue;
newObj[prop.toLowerCase()] = this[obj][prop];
}
newArr.push(newObj);
}
return newArr;
};
response.send(JSON.stringify(results));
});
}

How to remove duplicate objects from JavaScript array

This is my code
var studentsList = [
{"Id": "101", "name": "siva"},
{"Id": "101", "name": "siva"},
{"Id": "102", "name": "hari"},
{"Id": "103", "name": "rajesh"},
{"Id": "103", "name": "rajesh"},
{"Id": "104", "name": "ramesh"},
];
function arrUnique(arr) {
var cleaned = [];
studentsList.forEach(function(itm) {
var unique = true;
cleaned.forEach(function(itm2) {
if (_.isEqual(itm, itm2)) unique = false;
});
if (unique) cleaned.push(itm);
});
return cleaned;
}
var uniqueStandards = arrUnique(studentsList);
document.body.innerHTML = '<pre>' + JSON.stringify(uniqueStandards, null, 4) + '</pre>';
OutPut
[
{
"Id": "101",
"name": "siva"
},
{
"Id": "102",
"name": "hari"
},
{
"Id": "103",
"name": "rajesh"
},
{
"Id": "104",
"name": "ramesh"
}
]
In the above code I got unique objects from the JavaScript array, but i want to remove duplicate objects. So I want to get without duplicate objects from the array, the output like
[
{
"Id": "102",
"name": "hari"
},
{
"Id": "104",
"name": "ramesh"
}
]
Check this
var uniqueStandards = UniqueArraybyId(studentsList ,"id");
function UniqueArraybyId(collection, keyname) {
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key = item[keyname];
if(keys.indexOf(key) === -1) {
keys.push(key);
output.push(item);
}
});
return output;
};
This maybe? (not the most performant implementation but gets the job done):
var studentsList = [
{Id: "101", name: "siva"},
{Id: "101", name: "siva"},
{Id: "102", name: "hari"},
{Id: "103", name: "rajesh"},
{Id: "103", name: "rajesh"},
{Id: "104", name: "ramesh"},
];
var ids = {};
studentsList.forEach(function (student) {
ids[student.Id] = (ids[student.Id] || 0) + 1;
});
var output = [];
studentsList.forEach(function (student) {
if (ids[student.Id] === 1) output.push(student);
});
console.log(output);
Edit: faster method if the students are ordered by Id:
var studentsList = [
{Id: "101", name: "siva"},
{Id: "101", name: "siva"},
{Id: "102", name: "hari"},
{Id: "103", name: "rajesh"},
{Id: "103", name: "rajesh"},
{Id: "104", name: "ramesh"},
];
var output = [];
studentsList.reduce(function (isDup, student, index) {
var nextStudent = studentsList[index + 1];
if (nextStudent && student.Id === nextStudent.Id) {
return true;
} else if (isDup) {
return false;
} else {
output.push(student);
}
return false;
}, false);
console.log(output);
var unique = arr.filter(function(elem, index, self) {
return index === self.indexOf(elem);
})
You can use javascript's filter method:
The solution for the above problem can be found in this fiddle.
The performance of this solution will be better because we are using pure javascript and there is no third party overhead.
app.controller('myCntrl',function($scope){
var seen = {};
//You can filter based on Id or Name based on the requirement
var uniqueStudents = studentsList.filter(function(item){
if(seen.hasOwnProperty(item.Id)){
return false;
}else{
seen[item.Id] = true;
return true;
}
});
$scope.students = uniqueStudents;
});
Let me know if you need any other details.
Here is the controller which will detect the duplicate element and remove it and will give you the element which has no duplicates. Just use this controller
$scope.names= studentsList.reduce(function(array, place) {
if (array.indexOf( studentsList.name) < 0)
array.push( studentsList.name );
else
array.splice(array.indexOf( studentsList.name), 1);
return array;
}, []);
Hope this works for your case
You can use library lodash and method uniqBy()
How about this one-liner function using Set()?
function arrUnique(arr) { return [...new Set(arr.map(JSON.stringify))].map(JSON.parse);}
It uses JSON.stringify() and JSON.parse() to transform the objects to string, because the equality function of Set() (===) is not customizable and doesn't work for objects, but for strings. JSON.parse() of the unique elements in the stringified version transforms them back to objects.
Very likely, this is not the fastest version because of overhead using JSON methods.
How about this, two different examples, the first gets all duplicates comparing a property rather than an Id or comparing the whole object. The second example is is a distinct list of duplicates.
// Sample 1 - Show all duplicates of a particular code rather than the whole record is unique
var sampleJson =
[
{ id: 1, code: "123-123" },
{ id: 2, code: "123-124" },
{ id: 3, code: "123-125" },
{ id: 4, code: "123-123" }
];
console.log("All duplicates");
let duplicates= [];
sampleJson.forEach(function (item) {
var checkForDuplicates = sampleJson.filter(a => a.code == item.code);
if (checkForDuplicates.length > 1) {
duplicates .push(item);
}
});
console.log(duplicates);
console.log( "Distinct duplicates");
// Sample 2 - Distinct list of duplicates
let distinctDuplicates= [];
sampleJson.forEach(function(item) {
var checkForDuplicates = sampleJson.filter(a => a.code == item.code);
if (checkForDuplicates.length > 1) {
// Ensure we only have the single duplicate by ensuring we do not add the same one twice
var exists = distinctDuplicates.filter(b => b.code == item.code).length == 1;
if (false === exists) {
distinctDuplicates.push(item);
}
}
});
console.log(distinctDuplicates);

Categories