Reputation: 185
This is an array of objects:
const movies = [
{
title: "Terminator",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Die Hard",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Get Out",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
},
]
I would like to sort them by title
and genre.name
.
I want to create 2 new arrays, one is sorted by title
and the other one is sorted by genre.name
.
So far I tried this, but it was clearly wrong:
const sortMovies = (item) => {
movies.sort((a, b) =>
a.item> b.item? 1 : b.item> a.item? -1 : 0
);
};
const sortTitle = sortMovies(title);
const sortGenre = sortMovies(genre.name);
Please help me find a solution to this. I really appreciate it!
Upvotes: 1
Views: 675
Reputation: 464
A sort higher order function only takes 1/-1
so passing 0
shouldn't work as far as I know.. But if you wanna sort the items as the item
provided by the sortMovies
function argument you have to do the following:
const movies = [
{
title: "Terminator",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Die Hard",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Get Out",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
},
]
let sortsMovies = (properties) => {
return movies.sort((a, b) => {
try {
const propertyArr = properties.split(".");
// this gets properties from the end of the object nest
const props1 = propertyArr.reduce((obj, prop) => obj[prop], a);
const props2 = propertyArr.reduce((obj, prop) => obj[prop], b);
return props1 > props2 ? 1 : -1;
}
catch (error) {
console.error('error:', error)
}
});
}
const genre = sortsMovies("genre.name")
const title = sortsMovies("title")
console.log('title:', title)
console.log('genre:', genre)
This should sort the Array of Object with the provided property
Upvotes: 1
Reputation: 14208
It seems that you want to compare title
then genre.name
.
So you can combine those criteria in this way
a.title.localeCompare(b.title) || a.genre.name.localeCompare(b.genre.name)
const movies = [
{
title: "Terminator",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Die Hard",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Get Out",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "B" },
},
{
title: "Get Out",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "A" },
},
];
const sortMovies = (data) => {
data.sort((a, b) =>
a.title.localeCompare(b.title)|| a.genre.name.localeCompare(b.genre.name));
}
sortMovies(movies);
console.log(movies);
As you can see, title = Get Out
is also sorted by genre.name
I want to create 2 new arrays, one is sorted by title and the other one is sorted by genre.name.
In case you want to create a generic method
const sortMovies = (data, getValueByProp) => {
data.sort((a, b) =>
{
const v1 = getValueByProp(a);
const v2 = getValueByProp(b);
return v1.localeCompare(v2);
});
}
sortMovies(movies, (item) => item.title);
sortMovies(movies, (item) => item.genre.name);
const movies = [
{
title: "Terminator",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Die Hard",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Get Out",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "B" },
},
{
title: "Get Out",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "A" },
},
];
const sortMovies = (data, getValueByProp) => {
data.sort((a, b) =>
{
const v1 = getValueByProp(a);
const v2 = getValueByProp(b);
return v1.localeCompare(v2);
});
}
sortMovies(movies, (item) => item.title);
console.log(movies);
sortMovies(movies, (item) => item.genre.name);
console.log(movies);
Upvotes: 1
Reputation: 1051
just change it like this
const sortMovies = (item) => {
return movies.sort((a, b) =>
a[item]> b[item]? 1 : b[item]> a[item]? -1 : 0
);
};
const sortTitle = sortMovies("title");
For more nested: I don't recommend this because of performance issue. Just to show the possibility
function getPropByString(obj, propString) {
if (!propString)
return obj;
var prop, props = propString.split('.');
for (var i = 0, iLen = props.length - 1; i < iLen; i++) {
prop = props[i];
var candidate = obj[prop];
if (candidate !== undefined) {
obj = candidate;
} else {
break;
}
}
return obj[props[i]];
}
const sortMovies = (item) => {
return movies.sort((a, b) =>
getPropByString(a,item) > getPropByString(b,item)? 1 : getPropByString(b,item) > getPropByString(a,item) ? -1 : 0
);
};
const sortTitle = sortMovies("title");
const sortGenre = sortMovies("genre.name");
Upvotes: 1
Reputation: 5264
the following code snippet may help you
const movies = [
{
title: "Terminator",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Die Hard",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
},
{
title: "Get Out",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
},
];
//sort by title
var sortedByTitle = movies.sort( (a, b) => {
if(a.title < b.title) { return -1; }
if(a.title > b.title) { return 1; }
return 0;
} );
console.log(sortedByTitle);
//sort by genre
var sortedGenre = movies.sort( (a, b) => {
if(a.genre.name < b.genre.name) { return -1; }
if(a.genre.name > b.genre.name) { return 1; }
return 0;
} );
console.log(sortedGenre);
Upvotes: 1