Lodash orderBy returning empty array - javascript

I am trying to order an array with Objects in ascending order using lodash.orderBy npm module.
this is the example object I am using
var obj = [{ user: 'me', score: 100}, { user: 'you', score: 55}, { user: 'someone', score: 555 }]
Once I have that object, I pass it through as the first parameter and specify which key to orderBy.
let sort = orderBy(obj, 'score')
But this returns an empty array, is there something I am doing wrong ? based on the documentation this is correct: https://lodash.com/docs/4.17.4#orderBy
This may be an issue with the asynchronous call and saying the index of the Array is 0.
EDIT:

It seems as if you are not actually calling orderBy() on the lodash object. Try the following code:
JS
const _ = require('lodash');
var obj = [[{
user: 'me',
score: 100
},{
user: 'you',
score: 55
},{
user: 'someone',
score: 555
}]]
var data = obj[0];
let sort = _.orderBy(data, 'score');
console.log(sort);
Created a new variable data and assign it the value of obj[0] effectively assigning it the array. Lodash can then order the data as expected.
Console Output (score in ascending order by default)
[ { user: 'you', score: 55 },
{ user: 'me', score: 100 },
{ user: 'someone', score: 555 } ]
Possible solution for your code
let obj = this.state.items;
let data = obj[0];
let sort = lodash.orderBy(data, 'score');
console.log(sort);

Related

return a value of array that have special name

Im new in react js and I get a problem with my array... I want to return a value of my array that have contain name and adress .and all value are string thi is my data that I need
name :123,
adress:12569
const array = [
0: [ 'name','123' ],
1: [ 'adress','12569'],
2: ['family','4'],
];
You can run loop on the array and assign key-value for each of the array items.
const array = [
['name', '123'],
['adress', '12569'],
['family', '4'],
];
const res = {};
array.forEach((item) => {
res[item[0]] = item[1];
})
console.log(res);
In this case, you should use an Object.
const foo = {
name: '123',
adress: 'bar',
family: '4',
}
So, to access the propertys:
console.log(foo.name); // 123
console.log(foo.adress); // bar
console.log(foo.family); // 4
But if you are getting this information as an array, you can always transform it into an object.
It would make more sense for that data to be combined into a single object rather than a series of nested arrays, and then use find to locate the object that matches the query.
const data = [
{ name: 'Bob', address: '999 Letsbe Avenue', family: 4 },
{ name: 'Sally', address: '8 Treehouse Lane', family: 0 },
{ name: 'Joan', address: '85 Long Terrace', family: 6 }
];
// Accepts the data array, and a query object
function findFamily(data, query) {
// Iterate through the data array to `find`
return data.find(obj => {
// Split the query into key/value pairs
const queryEntries = Object.entries(query);
// And return only those objects where the
// object key/value matches the query key/value
return queryEntries.every(([ key, value ]) => {
return obj[key] === value;
});
// And if there are no matches return 'No match'
}) || 'No match';
}
console.log(findFamily(data, {
name: 'Bob',
address: '999 Letsbe Avenue',
family: 0
}));
console.log(findFamily(data, {
address: '999 Letsbe Avenue',
family: 4
}));
console.log(findFamily(data, {
name: 'Sally'
}));
Additional documentation
every
Destructuring assignment
Object.entries

Filtering array of objects against another array of objects?

customerProducts: [
{
name: "foo",
id: 123
},
{
name: "test",
id: 44
}
]
otherProducts: [
{
name: "other",
id: 44
},
{
name: "test",
id: 21
}
]
I want to iterate through customerProducts, which is an array of objects. I want to filter the customerProducts that have an ID that another array of objects, otherProducts, has. So for examople, I'd want the returned result in this case to be:
{
name: "test",
id: 44
}
since otherProducts has an id of 44.
I was thinking of mapping through otherProducts and just returning an array of IDs, then running a forEach on that but that seems like a long way of doing it.
Create an indexed Set of the values to filter by (id from otherProducts) then filter customerProducts by that Set
const customerProducts = [{name: "foo",id: 123},{name: "test",id: 44}]
const otherProducts = [{name: "other",id: 44},{name: "test",id: 21}]
const otherProductIds = new Set(otherProducts.map(({ id }) => id))
const filteredCustomerProducts = customerProducts.filter(({ id }) =>
otherProductIds.has(id))
console.info(filteredCustomerProducts)
This can be done by using array methods filter and some.
customerProducts.filter((x)=> otherProducts.some(y=> y.id === x.id));
Explanation:
filter method will call each and every element in the otherProducts array and check if the id of customerProduct is present in otherProducts for at least one element.
declare customerProducts , otherProducts as JS array variable and use JS Array filter find functions
let customerProducts = [
{
name: "foo",
id: 123
},
{
name: "test",
id: 44
}
]
let otherProducts = [
{
name: "other",
id: 44
},
{
name: "test",
id: 21
}
];
let filtered = customerProducts.filter( el => otherProducts.find( e => e.id == el.id) )
console.log(filtered);

creating a unique array in Javascript

Im having trouble creating an array that contains unique subset of a larger array, please help!
Original Array allMembers (6)[{},{},{},{},{},{}]
allMembers Payload: 0:{id:1, name: Alex} 1:{id:2, name: James} 2:{id:3, name: Bob} 3:{id:4, name: lara} 4:{id:5, name: Dan} 5:{id:6, name: Jes}
Second array uniqueMembers (3)[{},{},{}]
uniqueMembers Payload: 0:{id:1, name: Alex} 1:{id:2, name: James} 2:{id:3, name: Bob}`
what I'm looking for is to find the users that are in allMembers but not in uniqueMembers
so my desired new array output would be the following array resultArray
resultArray (3)[{},{},{}]
resultArray Payload: 0:{id:4, name: lara} 1:{id:5, name: Dan} 2:{id:6, name: Jes}
My attempt
for(let m=0; m<allMembers.length;m++)
{
console.log('Testing include statement', uniqueMembers.includes(allMembers[m])) //output always false
if(uniqueMembers.includes(allMembers[m]))
{
console.log('ITS ALREADY IN: ', allMembers[m])
}else{
this.setState((prevState) => ({
resultArray: [...prevState.resultArray, allMembers[m]]
}));
console.log('ITS NOT IN: ', allMembers[m])
}
}// resultArray ends up the same as allMembers :(
Any feedback on how I can get the desired resultArray values would be appreciated!
Build an associative array to efficiently lookup if a member should be filtered out.
lookup = {}
for (const um uniqueMembers)
lookup[um.id] = 1;
resultArray = allMembers.filter( mem => !lookup.hasOwnProperty(mem) );
Two solutions posted after this one suggested using filter and some. Those solutions are O(N2). This one is should be O(N), which is way better.
If your unique array is very huge as well, convert unique array to one set first, it will save time to loop the unique array to check the match.
Then uses Array.filter to get the not in unique elements.
let all = [{id:1, name: 'Alex'}, {id:2, name: 'James'},{id:3, name: 'Bob'},{id:4, name: 'lara'},{id:5, name: 'Dan'} ,{id:6, name: 'Jes'}]
let unique = [{id:2, name: 'James'},{id:3, name: 'Bob'}]
function getNotInUnique(src, target) {
let uniqueSet = new Set(target.map(member => member.id))
return src.filter(member => !uniqueSet.has(member.id))
}
console.log(getNotInUnique(all, unique))
You can use filter along with some.
const allMembers = [
{id:1, name: 'Alex'},{id:2, name: 'James'},{id:3, name: 'Bob'}, {id:4, name: 'lara'}, {id:5, name: 'Dan'}, {id:6, name: 'Jes'}
];
const uniqueMembers = [
{id:1, name: 'Alex'},{id:2, name: 'James'},{id:3, name: 'Bob'}
];
const res = allMembers.filter(m => !uniqueMembers.some(({id})=>m.id===id));
console.log(res);

Assert sorted array of objects [duplicate]

This question already has an answer here:
Map and Sort in one iteration in Javascript?
(1 answer)
Closed 4 years ago.
I'm doing unit testing using javascript testing framework (mocha, chai, etc). How can I assert my array of objects using its name?
I can successfully sort this using localeCompare but I'm not getting what I wanted on my test. It just returns 1 or -1.
Here's my a sample of what I want to sort.
var Stuffs = [
{ name: "PWE", address: "1234567890" },
{ name: "NSA", address: "1234567890" },
{ name: "AVE", address: "1234567890" },
{ name: "QRE", address: "1234567890" },
]
How can I assert this to ["AVE", "NSA", "PWE", "QRE"] ?
To get your desired Array, you can use:
Stuffs.map(({ name }) => name).sort();
You could also use reduce() method of array and then sort().
DEMO
var Stuffs = [{ name: "PWE", address: "1234567890" },
{ name: "NSA", address: "1234567890" },
{ name: "AVE", address: "1234567890" },
{ name: "QRE", address: "1234567890" }];
let sortedArr = Stuffs.reduce((r,{name})=>r.concat(name),[]).sort((a,b)=>a.localeCompare(b));
console.log(sortedArr);
Using chai
assert.deepInclude(Stuffs, {name: "AVE"});
assert.deepInclude(Stuffs, {name: "NSA"});
assert.deepInclude(Stuffs, {name: "QRE"});
assert.deepInclude(Stuffs, {name: "PWE"});
Edit: I may have misunderstood it to mean, how can assert that the array has those values.
First you would need a sorted array to compare it to. The original array needs to be cloned (shallow is fine for this) since sort will modify the array it is called on. Using from to generate the clone, we can then alphabetically sort the new array to get the desired order.
const sortedStuffs = Array.from(stuffs).sort(({name: a}, {name: b}) => a.localeCompare(b));
Finally using every, we can compare the names for each element to see if they match. As soon as one fails, the returned value will be false
stuffs.every(({name}, i) => name === sortedStuffs[i].name);
Full working example:
const stuffs = [
{name: "PWE", address: "1234567890"},
{name: "NSA", address: "1234567890"},
{name: "AVE", address: "1234567890"},
{name: "QRE", address: "1234567890"}
];
const sortedStuffs = Array.from(stuffs).sort(({name: a}, {name: b}) => a.localeCompare(b));
const isSorted = stuffs.every(({name}, i) => name === sortedStuffs[i].name);
console.log(isSorted);

Javascript arrays and objects: Get differences and merge them

So I have this scenario where I have a client-app which sends data (array of objects) to a server which then forwards the data to other clients connected to this server.
In the client-app, the data is constantly changing, meaning: Values change, new objects inside the array pop up, objects being removed, and so on ...
Now I want the other clients to always receive the latest data. And because I dont want the client-app to just push the whole new data to the server which then forwards the whole new data to the other clients, I decided to let the client-app only push the changes (using this library: https://www.npmjs.com/package/deep-object-diff).
The other clients then receive an array of objects with only the data that has actually changed and because they know the previous data array, I want them to "merge" the array of changes with the old data object.
My actual problem is the merging. I dont know how to properly do this. Especially if I have an array of objects without any key for the objects.
So my data looks something like this:
let data = [
{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 33,
sID: 554589525469
}
];
Actually there's much more but well, thats the structure.
So if the diff library says, this are the changes:
let changes = {
{
age: 34,
sID: 554589525469
}
};
(notice that I now have an object of objects, not an array of objects. Thats what the diff-library returns)
I want the merged object to be
[
{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 34,
sID: 554589525469
}
];
(John is now one year older)
So I totally believe that this would be much easier if I had a key to the objects as an identifier, but still I think there has to be a solution for exactly this scenario. And as you can see, the sID property could act as an identifier, its just not a key.
I would apprectiate if someone could point out how to do it in both cases (with and without a specific key for the objects)
You can use .find() to find the object within the array where values should be changed, Object.assign() to set the values
let data = [{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 33,
sID: 554589525469
}
];
let changes = [{
age: 34,
sID: 554589525469
}];
for (let prop of changes) {
let {sID} = prop;
Object.assign(data.find(({sID: id}) => id === sID), prop)
}
console.log(data);
You could use a sId Map for fast lookup:
const byId = new Map( data.map( el => [el.sID, el]));
Then for every change we can find if the obj already exists, if not we add it, if yes we mutate:
changes.forEach(change => {
const res = byId.get( change.sID );
if( res ){
Object.assign( res, change);
}else{
data.push(change);
byId.set( change.sID, change);
}
});
Using lodash, you can accomplish this with unionBy :
const newData = _.unionBy(changes, data, 'sID'); // values from changes will be picked
This will pick objects from both the arrays based on sID and combine them into a single array.
If your changes data is object of objects , you can use Object.values to loop data value and merge same id data by Object.assign
let data = [
{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 33,
sID: 554589525469
}
];
let changes = {
0:
{
age: 34,
sID: 554589525469
}
};
data.filter((idx,i)=>
Object.values(changes).forEach((index)=>
(index.sID == idx.sID) ? Object.assign(data[i],index) : null
)
);
console.log(data);

Categories

Resources