Javascript使用嵌套属性排序对象数组,其中某些属性未定义

时间:2016-01-06 22:44:26

标签: javascript sorting

我正在尝试实现一个排序函数,该函数接收一个对象数组并按属性或嵌套属性对它们进行排序。我已经在这里看了很多问题,并且对这个问题有了很好的答案,但据我所知,没有一个问题可以解释何时缺少嵌套属性。

例如,如果我按some_attributesome_attribute = undefined对我的一个数组元素进行排序,那么有问题的元素会碰到数组的结尾/开头,正如我所料。如果按some_attribute.something_else排序,我看到的功能在some_attribute.something_else = undefined时效果不佳。

以下是我正在尝试排序的数据结构示例:

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
    }
]

现在,如果我运行下面的代码,那么当我期望[2, 3, 5, undefined]时,我会得到[undefined, 2, 3, 5]

results.sortBy('twitter_link_click_count.total').map(function(x){return x.twitter_link_click_count.total})

在上面的代码段中,sortBy是来自this post的函数,但我也尝试使用具有相同结果的Underscore的_.sortBy函数。

工作代码

根据Oleg的回答,我提出了解决方案:

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;
        };
    });
};

这里的关键区别在于它生成一个sortKey数组,可以使用if / else语句或迭代。我使用了if / else,因为我的sortKey在我的对象中只有1或2层深。我还通过返回null而不是0来处理我的属性为true的情况。希望这有助于其他人。

2 个答案:

答案 0 :(得分:1)

请尝试以下脚本(在那里使用Underscore):

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>

答案 1 :(得分:0)

使用普通JS过滤器的解决方案&amp;图

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
})