Javascript copy no repeat object data taht have same property from array - javascript

I have an arrry that has 100 object and it has same property code
Data = [
{yera:"2019", name:"saif", topic:"oil"},
{yera:"2018", name:"abc", topic: "oil"},
{yera:"2018", name:"jorj", topic:"energy"},
{yera:"2017", name:"tom", topic:"gas"},
{yera:"2016",name:"saif",topic:"electricity "},
{yera:"2014", name:"gour",topic:"oil"},

Assuming you want to remove duplicates from the array of objects based on a key of that object, the code below will achieve that.
var data = [
{yera:"2019", name:"saif", topic:"oil"},
{yera:"2018", name:"abc", topic: "oil"},
{yera:"2018", name:"jorj", topic:"energy"},
{yera:"2017", name:"tom", topic:"gas"},
{yera:"2016",name:"saif",topic:"electricity "},
{yera:"2014", name:"gour",topic:"oil"}
]
function getUniqueData(originalData, keyToCheckForUniqueness) {
var store = {};
var output = [];
originalData.forEach(function (ob) {
var val = ob[keyToCheckForUniqueness];
if (!store[val]) {
store[val] = [ob];
} else {
store[val].push(ob);
}
});
// at this point your store contains all the repeating data based on that property value
// console.log(store);
// now emit single values from that store;
// this logic can be based on any criterion, I chose the first element of the array - it may change depending on the order of values in input
Object.keys(store).forEach(function (key) {
var uniqueValArray = store[key];
var uniqueVal = uniqueValArray[0]; // take the first entry
output.push(uniqueVal);
});
return output;
}
getUniqueData(data, "topic");
This will achieve what I think you want to figure out. A word of advice - Don't let people think when you ask them for help. Second, try writing the logic for yourself. Post your non-working solution and ask, where you made a mistake - rather than asking. Given your rep, welcome to SO. Hope you a great learning experience.

Assuming, you want unique values for a given property of the objects, you could map that value and take a Set for getting unique values.
function getUnique(array, key) {
return Array.from(new Set(array.map(({ [key]: v }) => v)));
}
var array = [{ year: "2019", name: "grace", topic: "oil" }, { year: "2018", name: "grace", topic: "oil" }, { year: "2018", name: "jane", topic: "energy" }, { year: "2017", name: "tom", topic: "gas" }, { year: "2016", name: "jane", topic: "electricity" }, { year: "2014", name: "gour", topic: "oil" }];
console.log(getUnique(array, 'year'));
console.log(getUnique(array, 'name'));
console.log(getUnique(array, 'topic'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How to filter few properties of an object which is in Array of objects if one property equals property from another object

I have a object which has some properties for one user, and I have array of objects which is returned from API.
My goal is to check which object of Array of objects has the same property as the one single initial object, and then it should return only part of it's properities.
I have tried to use .map on Array of objects but it seems not workig.
Below is the code example. I have also prepared codesandbox if You wish.
const user =
{
name: "jan",
lastName: "kowalski",
fullName: "jan kowalski",
car: "audi"
}
;
const usersAnimal = [
{
name: "jan",
lastName: "kowalski",
fullName: "jan kowalski",
animal: "cat",
animalSize: "small",
animalName: "Bat"
},
{
name: "john",
lastName: "smith",
fullName: "john smith",
animal: "dog",
animalSize: "middle",
animalName: "Jerry"
},
{
name: "Anna",
lastName: "Nilsson",
fullName: "Anna Nilsson",
animal: "cow",
animalSize: "big",
animalName: "Dorrie"
}
];
const filtered = usersAnimal.map((userAnimal)=>userAnimal.fullName === user.fullName && return userAnimal.animalName & userAnimal.animalSize & userAnimal.animal);
thanks
https://codesandbox.io/s/admiring-edison-qxff42?file=/src/App.js
For case like this, it would be far easier if you filter it out first then proceed using map:
const filtered = usersAnimal
.filter((animal) => animal.fullName === user.fullName)
.map(({ animalName, animalSize, animal }) => {
return {
animalName,
animalSize,
animal
};
});
I am providing a for loop solution as I haven't learnt many array methods in javascript.
For me the simplest option is to use a for loop and an if check to loop through the arrays values to check for included values.
for (let v in usersAnimal) {
if (usersAnimal[v].fullName === user.fullName) {
console.log(usersAnimal[v])
}
}
The code above will log the entire usersAnimal object containing the fullname we are looking for.
{
name: 'jan',
lastName: 'kowalski',
fullName: 'jan kowalski',
animal: 'cat',
animalSize: 'small',
animalName: 'Bat'
}
commented for further understanding
for (let v in usersAnimal) {
//loops though the array
if (usersAnimal[v].fullName === user.fullName) {
//when the index value 'v' has a fullname that matches the user fullname value
// it passes the if check and logs that object value
return console.log(usersAnimal[v])
//return true...
}
//return null
}
//etc
If you want to filter, I recommend you to use filter.
The map method will create a new array, the content of which is the set of results returned by each element of the original array after the callback function is operated
const user = {name:"jan",lastName:"kowalski",fullName:"jan kowalski",car:"audi"};
const usersAnimal = [{name:"jan",lastName:"kowalski",fullName:"jan kowalski",animal:"cat",animalSize:"small",animalName:"Bat"},{name:"john",lastName:"smith",fullName:"john smith",animal:"dog",animalSize:"middle",animalName:"Jerry"}];
// Get an array of matching objects
let filtered =
usersAnimal.filter(o => o.fullName === user.fullName);
// You get the filtered array, then you can get the required properties
filtered.forEach(o => {
console.log(
'animal:%s, animalSize:%s, animalName:%s',
o?.animal, o?.animalSize, o?.animalName
);
});
// Then use map to process each element
filtered = filtered.map(o => {
const {animal, animalSize, animalName} = o;
return {animal, animalSize, animalName};
});
console.log('filtered', filtered);

MongoDB get ArrayFilters reference to update value

I recently started using MongoDB and I'm trying to update a few properties from a document but not being able to get the object reference to update a value.
Please consider the following data:
const data = {
weekplanId: 'someid',
days: [
{label: 'Monday', cost: 20, comment: "some comment" },
{label: 'Tuesday', cost: 40, comment: "..." }
]
}
const update = await weekplan.updateOne(
{
_id: new ObjectId(data.weekplanId),
},
{
$set: {
"weekdays.$[i].cost": data.days.$[i].cost,
"weekdays.$[i].comment": data.days.$[i].comment,
"weekdays.$[i].date": new Date(),
"weekdays.$[i].someproperty": "something",
}
},
{
arrayFilters: [
{
"i.label": {
$in: data.days.map(p => p.label),
},
}]
}
);
How can I reference the array object to set the property value?
I know data.days.$[i].cost and data.days.$[i].comment are wrong, they are just an example of what I'm trying to achieve.
Setting the date and someproperty works as expected, since the values are not dependent on the source data.
I would like to try to do this without using JS.
Is arrayFilters even appropriate for this? I'd appreciate some guidance as to where to look at.
Thanks in advance!
###EDIT:
Expected output:
"_id": {"someid"},
"weekdays": [
{
"day": "Monday",
"cost": 20,
"comment": "some comment",
"date": 2021-08-01T19:51:45.057Z
"someproperty": "something"
},
{
"day": "Tuesday",
"cost": 40,
"comment": "...",
"date": 2021-08-01T19:51:45.057Z
"someproperty": "something"
},
...
...
...
]
The rest of the week days (Wednesday, Thursday, Friday) would remain untouched on this update.
In that example code data.days.$[i].cost is evaluated on the client side, before the query is submitted, so whatever value (or lack thereof) that is has will be assigned to the corresponding field of the $set object when the server receives it.
The data object will not be sent to the server with the query, so even if it were able to do array lookup on input values, the input value would not be there.
The way to accomplish this is to iterate the array on the client side, and programmatically build the update query. Perhaps something like:
let labelChar = 105;
let setOps = {};
let filters = {};
data.days.forEach( function(day) {
let char = String.fromCharCode(labelChar++);
setOps['weekdays.$[' + char + '].cost'] = day.cost;
setOps['weekdays.$[' + char + '].comment'] = day.comment;
setOps['weekdays.$[' + char + '].date'] = new Date();
setOps['weekdays.$[' + char + '].someproperty'] = "something";
let filterObj = {};
filterObj[char + '.label'] = day.label;
filters.push(filterObj);
});
const update = await weekplan.updateOne(
{
_id: new ObjectId(data.weekplanId),
},
{
$set: setOps
},
{
arrayFilters: filters
}
);
For the provided sample input, this will give the update:
.updateOne(
{
_id: new ObjectId(data.weekplanId),
},
{
$set: {
'weekdays.$[i].cost': 20,
'weekdays.$[i].comment': 'some comment',
'weekdays.$[i].date': ISODate(),
'weekdays.$[i].someproperty': 'something',
'weekdays.$[j].cost': 40,
'weekdays.$[j].comment': '...',
'weekdays.$[j].date': ISODate(),
'weekdays.$[j].someproperty': 'something'
}
},
{
arrayFilters: [
{'i.label': 'Monday'},
{'j.label': 'Tuesday'}
]
}
);

Objects inside Array, how to solve this problem?

My question is, how can i access each object inside an Array? or
perhaps, how am I supposed to solve this problem? Like I know in head,
i have to compare categories and then push into new const array that
category. So far, i get each object in array wrote down, but I need to
do an push method after category is same, and also after that to
splice the category from each object.
My solution so far:
export const convert = inside => {
inside(({id,name,category}) => {
outside[category].push({id,name});
});
console.log(outside);
return outside;
}
Sorry for messed code, could not load here.
You could take the category as key for the object and push a new object.
No need for an array for every category, because this appoach uses the result object with dynamic keys.
const
inside = [{ id: 1, name: "orange", category: "fruits" }, { id: 2, name: "apple", category: "fruits" }, { id: 3, name: "carrot", category: "vegetable" }],
outside = {};
inside.forEach(({ id, name, category }) => {
outside[category] = outside[category] || [];
outside[category].push({ id, name });
});
console.log(outside);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I'm not fully sure i understand the question but from what i think is needed, you want to take all the items from the outside constant and take their respective category, apply it to the food Object and then add that Object to the inside variable.
const outside = {
fruits: [{
id: 1,
name: "orange"
}, {
id: 2,
name: "apple"
}],
vegetable: [{
id: 3,
name: "carrot"
}]
}
const categories = Object.keys(outside)
let inside = []
categories.forEach(category => {
const categorizedFood = outside[category].map(f => ({...f, category }) )
inside = [...inside, ...categorizedFood]
})
console.log(inside)
.as-console-wrapper {
background: #FFF;
filter: invert(1) hue-rotate(210deg);
}

How to weight items in a fuzzy search

Using Fuse.js, I need to weight individual item for a better ranking in search results. For instance, how do I make sure "Paris France" has the biggest score for a "Paris" query with the data below?
places = [{
name: 'Paris, France'
weigth: 10
},{
name: 'Paris, Ontario'
weigth: 2
},
{
name: 'Paris, Texas'
weigth: 1
}]
As far as I am aware, there are no methods built into Fuse.js to do this. The weight property is meant to be applied to properties which are being searched (in the options object), rather than to the object that is being searched (as seen in the example here.
What I might suggest is writing a function to sort this yourself. So once you get your results array back, after the search, perform an Array.sort() on it yourself (documentation here).
For example...
//Your places object
var places = [
{
name: 'Paris, Texas',
weight: 2
},
{
name: 'Paris, France',
weight: 10
},
{
name: 'Paris, Texas',
weight: 1
}
];
//Your search options
var options = {
keys: [
"name"
]
};
var fuse = new Fuse(places, options); // "list" is the item array
var result = fuse.search("Paris");
//Once you have got this result, perform your own sort on it:
result.sort(function(a, b) {
return b.weight - a.weight;
});
console.log('Your sorted results:');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/3.1.0/fuse.min.js"></script>

Loop through an array of objects and get where object.field equals value

I'm currently working on a small application where I have to loop through an enormous array of objects. What would be the most efficient method to perform this?
var array = [
{
id: "1",
name: "Alpha"
},
{
id: "2",
name: "Beta"
},
...
];
I'd like to get each object where name equals "Alpha". I'm currently using a simple if statement to filter the objects with a different name value out, but I wonder if there's a more efficient way to do this, performance-wise.
It's worth to mention that I'll push the matching results into a new array.
No, there is no more efficient way.
The alternative is to build and maintain some kind of internal data structure which allows you to find the desired elements faster. As usual, the trade off is between the work involved in maintaining such a structure vs the time it saves you.
I don't have any way about which I would know it's more effective.
But if you had your objects ordered by name you could stop your search imideatly upon reaching an object whose name is not equal to "Alpha".
To find the first object you're looking for you can use binary search and from this Object you go up and down until at both ends you reach an object which isn't named "Alpha" or the end of array.
This is only a way of optimizing and will require time to sort the array and also will take more time when adding an element.
There's a JavaScript function exactly for this kind of task. Filter
From the Docs
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
Here is a small example by code for getting all element from array which has a certain 'name' field:
const arr = [
{name: 'Abc'},
{name: 'Xyz'},
{name: 'Lmn'},
{name: 'Xyz'},
{name: 'Xyz'}
];
let response = findByName('Xyz');
console.log(response);
function findByName (name) {
return arr.filter((element) => {
return element.name = name;
});
}
If you need more than one time a collection with a given name, you could use an object with the names as hashes and have instantly access to the items.
var array = [{ id: "1", name: "Alpha" }, { id: "2", name: "Beta" }, { id: "3", name: "Beta" }, { id: "4", name: "Gamma" }, { id: "5", name: "Beta" }, { id: "2", name: "Alpha" }],
hash = Object.create(null);
array.forEach(function (a) {
if (!hash[a.name]) {
hash[a.name] = [];
}
hash[a.name].push(a);
});
console.log(hash);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories