Reputation: 4997
I'm trying to implement a sorting function that takes in an array of objects and sorts them by an attribute or a nested attribute. I've looked at a ton of questions on here with good answers to this problem, but so far as I have seen, none of them account for when a nested attribute is missing.
For example, if I sort by some_attribute
and some_attribute = undefined
for one of my array elements, the element in question is bumped to the end/beginning of the array, as I would expect. If I sort by some_attribute.something_else
, the functions I've seen don't respond well when some_attribute.something_else = undefined
.
Here is a sample of my data structure I'm trying to sort:
results = [
{
id: 233,
post: "Test 944 AM http://frmply.co/1mA9G3L",
twitter_favorite_count: 0,
twitter_retweet_count: 2,
twitter_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 3
},
twitter_last_updated: "2015-12-28T21:11:27.425Z",
facebook_like_count: null,
facebook_share_count: 1,
facebook_comment_count: null,
facebook_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 1
},
facebook_last_updated: "2015-12-28T21:11:29.232Z",
linkedin_like_count: null,
linkedin_comment_count: null,
linkedin_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 0
},
linkedin_last_updated: "2015-12-28T21:11:29.905Z"
},
{
id: 232,
post: "Test 944 AM http://frmply.co/1mA9G3L",
twitter_favorite_count: null,
twitter_retweet_count: null,
twitter_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 5
},
twitter_last_updated: null,
facebook_like_count: null,
facebook_share_count: null,
facebook_comment_count: null,
facebook_link_click_count: { },
facebook_last_updated: null,
linkedin_like_count: null,
linkedin_comment_count: null,
linkedin_link_click_count: { },
linkedin_last_updated: null
},
{
id: 234,
post: "localhost test 1106am http://frmply.co/1RAYalE",
twitter_favorite_count: 0,
twitter_retweet_count: 0,
twitter_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 2
},
twitter_last_updated: "2016-01-06T18:40:21.388Z",
facebook_like_count: null,
facebook_share_count: null,
facebook_comment_count: null,
facebook_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 0
},
facebook_last_updated: "2015-12-29T16:07:39.042Z",
linkedin_like_count: null,
linkedin_comment_count: null,
linkedin_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 0
},
linkedin_last_updated: "2015-12-29T16:07:39.489Z"
},
{
id: 231,
post: "test",
twitter_favorite_count: null,
twitter_retweet_count: null,
twitter_link_click_count: { },
twitter_last_updated: null,
facebook_like_count: null,
facebook_share_count: null,
facebook_comment_count: null,
facebook_link_click_count: { },
facebook_last_updated: null,
linkedin_like_count: null,
linkedin_comment_count: null,
linkedin_link_click_count: { },
linkedin_last_updated: null
}
]
Now if I run the code below I get [2, 3, 5, undefined]
as a result when I would expect [undefined, 2, 3, 5]
.
results.sortBy('twitter_link_click_count.total').map(function(x){return x.twitter_link_click_count.total})
In the snippet above, sortBy
is a function from this post, however I've also tried using Underscore's _.sortBy
function with identical results.
Working Code
Here is the solution I came up with based off Oleg's answer:
var sortKey = attribute.split('.');
var sortBy = function(results, sortKey) {
return _.sortBy(results, function(item) {
if(sortKey.length === 1) {
return item[sortKey[0]] || 0;
} else {
return item[sortKey[0]][sortKey[1]] || 0;
};
});
};
The key difference here is that it generates a sortKey
array, which can be used an an if/else statement or iterated over. I used an if/else since my sortKey
is only ever 1 or 2 layers deep inside my object. I also handled cases where my attribute is null
by returning 0
instead of true
. Hope this helps someone else.
Upvotes: 0
Views: 97
Reputation: 1941
results = results.filter(function (a) {
return !!((a.twitter_link_click_count || {}).total)
}).sort(function(a, b){
return (a.twitter_link_click_count || {}).total > (b.twitter_link_click_count || {}).total
})
Upvotes: 0
Reputation: 4795
Please try the following script (used Underscore there):
results = [
{
id: 233,
post: "Test 944 AM http://frmply.co/1mA9G3L",
twitter_favorite_count: 0,
twitter_retweet_count: 2,
twitter_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 3
},
twitter_last_updated: "2015-12-28T21:11:27.425Z",
facebook_like_count: null,
facebook_share_count: 1,
facebook_comment_count: null,
facebook_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 1
},
facebook_last_updated: "2015-12-28T21:11:29.232Z",
linkedin_like_count: null,
linkedin_comment_count: null,
linkedin_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 0
},
linkedin_last_updated: "2015-12-28T21:11:29.905Z"
},
{
id: 232,
post: "Test 944 AM http://frmply.co/1mA9G3L",
twitter_favorite_count: null,
twitter_retweet_count: null,
twitter_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 5
},
twitter_last_updated: null,
facebook_like_count: null,
facebook_share_count: null,
facebook_comment_count: null,
facebook_link_click_count: { },
facebook_last_updated: null,
linkedin_like_count: null,
linkedin_comment_count: null,
linkedin_link_click_count: { },
linkedin_last_updated: null
},
{
id: 234,
post: "localhost test 1106am http://frmply.co/1RAYalE",
twitter_favorite_count: 0,
twitter_retweet_count: 0,
twitter_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 2
},
twitter_last_updated: "2016-01-06T18:40:21.388Z",
facebook_like_count: null,
facebook_share_count: null,
facebook_comment_count: null,
facebook_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 0
},
facebook_last_updated: "2015-12-29T16:07:39.042Z",
linkedin_like_count: null,
linkedin_comment_count: null,
linkedin_link_click_count: {
minute: null,
hour: null,
day: null,
week: null,
month: null,
total: 0
},
linkedin_last_updated: "2015-12-29T16:07:39.489Z"
},
{
id: 231,
post: "test",
twitter_favorite_count: null,
twitter_retweet_count: null,
twitter_link_click_count: { },
twitter_last_updated: null,
facebook_like_count: null,
facebook_share_count: null,
facebook_comment_count: null,
facebook_link_click_count: { },
facebook_last_updated: null,
linkedin_like_count: null,
linkedin_comment_count: null,
linkedin_link_click_count: { },
linkedin_last_updated: null
}
];
document.getElementById('output').innerHTML = JSON.stringify(_.sortBy(results, function(item) {
return item.twitter_link_click_count.total || true;
}).map(function(x){return x.twitter_link_click_count.total}));
<script src="http://underscorejs.org/underscore-min.js"></script>
<pre id="output"></pre>
Upvotes: 1