JS lodash uniq not woking with ObjectID list - lodash

I have a collection of mongoose models, I tried to use uniq lodash function to get unique id`s from the list, but still get the same list.
List elements are https://docs.mongodb.com/manual/reference/method/ObjectId/
const uniqueIds = uniq(ids) // not working
input:
[
5c6f98ceb3f013291b497d82,
5c6e447147c75d699f0514a1,
5c6e447147c75d699f0514a1,
5c6e447147c75d699f0514a1,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89
]
output:
[
5c6f98ceb3f013291b497d82,
5c6e447147c75d699f0514a1,
5c6e447147c75d699f0514a1,
5c6e447147c75d699f0514a1,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89,
5c6f98cfb3f013291b497d89
]

The issue is that these are ObjectId objects, and probably a new one is generated for the same hash, so in that case, the references aren't the same the following will probably happen:
ObjectId("foo") == ObjectId("foo"); // false
In that case uniq() won't be able to recognize the same ObjectId. A solution would be to use uniqBy() to properly compare them, for example:
_.uniqBy(ids, id => id.valueOf());

Since the items are instances of ObjectId, you can't use _.uniq() because different object instances are always unique. You can use lodash's _.uniqBy(), with the str property of the object as the unique identifier:
_.uniqBy(list, 'str')

Provided that the list is array, each element in the list is of the ObjectId, this should work. Each id in the list will be iterated and converted to sting for finding the unique elements
_.uniqBy(list, (id) => id.toString())

this will work even for objectId arrays
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
const uniqueArray=yourArray.filter(onlyUnique);

Related

how can i filter a array in Vue3

I am new to Vue3.
I have to filter a array with same item and push results into another array
My array is
let list = [
{"name":"1000","properties":{"item":"1","unit":"DZN"}},
{"name":"2000","properties":{"item":"1","unit":"CTN"}},
{"name":"3000","properties":{"item":"2","unit":"DZN"}},
{"name":"4000","properties":{"item":"3","unit":"CTN"}}
]
I need corresponding name with condition item =1 in another array.
Result array will be similar to [{"name":"1000", "unit":"DZN"}, {"name":"2000", "unit":"CTN"}]
TIA
If I understand correctly you want to create an array of objects with name and unit attributes from records which have item values equal to 1. To do that you have to first filter an array to get only records which have desired value of item and then map those values to create a new array of objects.
Here is an example:
let list = [
{"name":"1000","properties":{"item":"1","unit":"DZN"}},
{"name":"2000","properties":{"item":"1","unit":"CTN"}},
{"name":"3000","properties":{"item":"2","unit":"DZN"}},
{"name":"4000","properties":{"item":"3","unit":"CTN"}}
]
const filteredList = list.filter((e) => e.properties.item === "1").map((e) => { return {name: e.name, unit: e.properties.unit}});
console.log(filteredList);
If this is a Vue3 reactive variable remember to add .value before filter() method to make it work

VueJS2: How to pluck out one property of an array and use it to find matching value in the second array?

I have two arrays. I am trying to pluck out a property from one array and use it to find the value of another property in the other way. How to do this? Let me explain:
I have an array of objects that looks like so:
languageCodes:
{
"code1234char3": "mdr",
"name": "Mandar",
},
{
"code1234char3": "man",
"name": "Mandingo",
},
{
// etc...
},
I have another array of objects that looks like so:
divisionLanguages:
[
{
p_uID: 1,
nameLang3Char: 'mdr',
},
{
p_uID: 2,
nameLang3Char: 'man'
},
{
// etc..
}
]
I have a Vue template with an unordered list like so:
<ul v-for="x in divisionLanguages" :key="x.p_uID">
<li>Name: FOO
<li>Language: {{x.nameLang3Char}} - XXX</li> <--how to get 'name' value from 'languageCodes' and place here?
</ul>
Expected output should be:
Name: FOO
Language: mdr - Mandar
Name: BAR
Language: man - Mandingo
I tried to do something like in Vue SFC template (but did not work):
<li>Language: {{ languageName(x.nameLanguage3Char) }}</li>
...
methods: {
languageName(nameLanguage3Char) {
const name = this.divisionLanguages.filter(x => x.code6392char3 === nameLanguage3Char)
return name.name
}
I hope this makes sense of what I am trying to do.
Update: Thanks to #kellen in the comments, I change from filte() to find() like so:
languageName(nameLang3Char) {
const languageName = this.languageCodes.find(
x => x.code1234char3 == nameLang3Char
)
return languageName
},
and in I did:
<li>Language: {{ languageName(x.nameLang3Char).name }}</li>
and it works...but I get error in console:
Error in render: "TypeError: Cannot read property 'name' of undefined"
Have you tried combining these arrays before rendering them? If you were able to combine both objects before creating that list, that would make your life easier. Another thing I noticed is you're using filter, when find might be a better option to return a single value rather than an array. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

Ramda - extract object from array

I am trying to filter an array of objects with Ramda and it is working almost as I planned but I have one small issue. My result is array with one filtered object which is great but I need only object itself not array around it.
My example data set:
const principlesArray = [
{
id: 1,
harvesterId: "1",
title: "Principle1"
},
{
id: 2,
harvesterId: "2",
title: "Principle2"
},
]
And that is my Ramda query:
R.filter(R.propEq('harvesterId', '1'))(principlesArray)
As a result I get array with one filtered element but I need object itself:
[{"id":1,"harvesterId":"1","title":"Principle1"}]
Any help will be appreciated
You can use R.find instead of R.filter, to get the first object found:
const principlesArray = [{"id":1,"harvesterId":"1","title":"Principle1"},{"id":2,"harvesterId":"2","title":"Principle2"}]
const result = R.find(R.propEq('harvesterId', '1'))(principlesArray)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
A more generic approach would be to create a function that takes a predicate used by R.where, pass the partially applied R.where to R.find, and then get the results by applying the function to the array:
const { pipe, where, find, equals } = R
const fn = pipe(where, find)
const principlesArray = [{"id":1,"harvesterId":"1","title":"Principle1"},{"id":2,"harvesterId":"2","title":"Principle2"}]
const result = fn({ harvesterId: equals('1') })(principlesArray)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

How to access the data of the parent array when using v-for with an array in an array?

My data structure looks like this:
city: [
{
foo1: 0,
foo2: "Family",
districts: [
{
bar1: 0,
bar2: "event1",
}
]
},
My v-for looks like this.
<div v-for="district in city.districts" :bar1="district.bar1" :foo="???"></div>
How can I pass the foo1 and foo2 from the parent array as a prop to the div of the v-for?
Given your districts array is available via city.districts, I'd say you can use
<div v-for="district in city.districts"
:bar1="district.bar1" :foo1="city.foo1" :foo2="city.foo2">
</div>
Of course, these values will be the same for each district in a city but that looks like what you want.

Delete and add attributes with array.map and the spread operator

I'm trying to mangle data returned from an api. I've got an array of objects returned. I want to delete the password field and then add a couple of additional fields. I'd like to use the spread operator but my process feels a bit clunky.
myArray.map( item => {
const newItem = { ...item };
delete newItem.password;
newItem.saved = true;
return newItem;
});
Is there a nicer way to do this?
Given an array of objects -
const myArrayOfObjects = [
{id: 1, keyToDelete: 'nonsense'},
{id: 2, keyToDelete: 'rubbish'}
];
Delete the attribute keyToDelete, and add a new key newKey with the value "someVar".
myArrayOfObjects.map(({ keyToDelete, ...item}) => { ...item, newKey:'someVar'});
Updating the array to
[
{id: 1, newKey:'someVar'},
{id: 2, newKey:'someVar'}
]
See this great post for more information on the deletion method.