自定义orderby循环遍历嵌套数组

时间:2014-04-19 07:25:34

标签: javascript json angularjs

我的嵌套json正在杀了我,似乎我必须编写一个自定义过滤器来执行orderBy

$scope.ranking = [

    {
        'uId': 2,
            'name': 'Jeremy',
            'tabs': [{
            'tabId': 1,
                'points': 100,
        }, {
            'tabId': 2,
                'points': 10
        }],

    },

    {
        'uId': 3,
            'name': 'Jordon',
            'tabs': [{
            'tabId': 1,
                'points': 180,
            },{
            'tabId': 2,
                'points': 5
        }],
    }]


}

我想要的是排序用户'按分数排名。如果选项卡包含单个点,则会很容易,但是多个选项卡指示它们所玩的游戏类型。

看看我的小提琴,然后你就会知道我尝试做什么,http://jsfiddle.net/U4dd8/

我写了自定义过滤器,直到这里

app.filter("rankFilter", function(){
   return function (input, points) {
       var output = [];      

           for (var i in input) {

       for(var j in input[i].tabs){
        var points = input[i].tabs[j].points;

        output.push(points);

        }

       }   

    return output;
};

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您希望在每个标签中显示具有该类别点数的用户,并按点(针对该特定类别)对其进行排序。

这是一个非常本地化的问题(而不是与Angular相关),但这是一个可能的解决方案:

<强> HTML:

<li ng-repeat="user in ranking | orderByPointsForTab:currentTab">
    <a ng-click="showFriendsTasksEvent(user.uId)">
        {{user.name}} {{user.tabs | pointsForTab:currentTab}}
    </a>
</li>

使用了2个过滤器:

  1. pointsForTab:它需要一个tabs数组和currentTab作为参数,并返回与当前标签相关联的点。
    这也可以是控制器中的一个功能。

  2. orderByPointsForTab:它需要users数组和currentTab作为参数,并返回一个新数组,其中只包含具有当前选项卡的点并按降序排序的用户点数(对于当前标签)。

  3. <子> 为了理解下面的代码,您应该熟悉Array的以下方法(标准JS - 没有Angular特定的): <子>
    - Array.prorotype.forEach
    - Array.prorotype.some
    - Array.prorotype.map
    - Array.prorotype.sort

    app.filter("orderByPointsForTab", function () {
    
        /* `users` and `currentTab` as input */
        return function (users, currentTab) {
    
            /* 1: Create an array of users that have points
             *    for current tab (in random order) */
            var unsortedUsersWithPoints = [];
            (users || []).forEach(function (user) {
    
                /* Iterate over the tabs of each user... */
                (user.tabs || []).some(function (tab) {
    
                    /* ...until we find the current tab... */
                    if (tab.tabId === currentTab) {
    
                        /* ...store the user and the points for current tab
                         * for later access (see below)... */
                        unsortedUsersWithPoints.push({
                            user: user,
                            points: tab.points
                        });
    
                        /* ...and break the loop for the current user */
                        return true;
                    }
                });
            });
    
            /* 2: Sort the array of `{user, points}` objects 
             *    in descending order of points */
            var sortedUsersWithPoints = unsortedUsersWithPoints.sort(
                function (obj1, obj2) {
                    return obj2.points - obj1.points;
                }
            );
    
            /* 3: Create a new array containing only `user` objects,
             *    but keeping the order in `sortedUsersWithPoints` (see above) */
            var output = sortedUsersWithPoints.map(function (obj) {
                return obj.user;
            });
    
            /* 4. Return the sorted `users` array */
            return output;
        };
    });
    

    上述代码可在此 short demo

    中找到

答案 1 :(得分:0)

首先,由于您已在视图中显示currentTab,因此您可以使用users选择要为每个标签显示的ng-show,而不是使用额外的过滤器。然后,使用自定义过滤器(orderByPoints)实现自定义排序,根据标签点对用户进行排序。

您的观点变为

<div ng-controller="AppCtrl">
    <button ng-click="currentTab=1">shooting</button>
    <button ng-click="currentTab=2">dribble</button>
    <p>Leaderboard</p>
    <ul>
        <li ng-repeat="user in ranking | orderByPoints: currentTab"> 
            <span ng-repeat="tab in user.tabs">
                <span ng-show="tab.tabId == currentTab">
                    <a ng-click="showFriendsTasksEvent(user.uId)">
                        {{ user.name }} - {{ tab.points }}
                    </a>
                </span>
            </span>
        </li>
    </ul>
</div>

自定义过滤器

app.filter("orderByPoints", function () {
    var inputTab;
    function compare(a, b) {
        // Check for undefined since value may be missing for some users
        if (typeof a.tabs[inputTab] != 'undefined' && typeof b.tabs[inputTab] != 'undefined')
            return b.tabs[inputTab].points - a.tabs[inputTab].points;
        return 0;
    }
    // Filter function
    return function (input, currentTab) {
        inputTab = currentTab; // Get current tab
        return input.sort(compare); // Call custom sort
    }
});

以下是更新的Fiddle(我添加了额外的user和标签以供演示)。