簡體   English   中英

如何在Javascript數組中的某個對象之前獲取最后N個對象?

[英]How to get the last N objects before a certain object in a Javascript array?

我正在嘗試在Javascript中實現無限加載項目。 就像在您喜歡的消息傳遞應用程序中滾動消息時所獲得的效果一樣。 我有一個像這樣的大陣列(+1000個對象):

var array = [
    { id : 1, text: "First"},
    { id : 2, text: "Second"},
    { id : 3, text: "Third"},
    { id : 4, text: "Forth"},
    { id : 5, text: "Fifth"},
    { id : 6, text: "Sixth"},
    { id : 7, text: "Seventh"},
    ...
];

現在我想一次只加載10個項目。 例如,我只顯示ID為3039 現在用戶希望在30之前看到這些項目。 在id為30對象之前選擇最后10個項目的最佳方法是什么? 如前所述,陣列的大小很大,所以性能在這里很重要。

編輯

上面的例子只是一個例子。 我應該能夠根據需要一次多次過濾我的數組10個項目。

我想要實現的是加載一個大陣列,但不是一次性加載。 我想一次加載10個項目。 我正在跟蹤我的過濾數組中的第一個對象(例如30 ),然后我想在該特定對象之前獲取最后10個對象。

編輯2

這是我的觀點:

<div ng-repeat="message in messages" class="message-wrapper">
     // Show content of message 
</div>

現在我最初在消息中顯示最后10項

$scope.init = function(){        
    var messages = Database.AllMessages(); // This function returns all my messages
    $scope.messages =  messages.length > 10 ? messages.slice(-10) : messages;        
}

現在假設此函數返回的項目是Id為3039 用戶向上滾動並希望在30之前看到消息。 那么如何過濾AllMessages()返回的整個數組以獲得30消息之前的10個最后一項?

提前感謝任何見解。

您希望盡可能高效地查詢數據源。 確保數組首先按id排序:

array.sort(function(a, b) {
  if (a.id === b.id) return 0;
  if (a.id > b.id) return 1;
  return -1;
});

然后,可以執行二進制搜索以查找您要查找的元素的索引:

var search = function(arr, val) {
    if (arr.length === 0) {
        return -1;
    }

    var max = arr.length - 1, min = 0;

    while (max !== min) {
        var index = Math.floor((max + min) / 2);

        if (arr[index].id === val) {
            return index;
        }
        else if (arr[index].id < val) {
            min = index;
        }
        else {
            max = index;
        }
    }
    return arr[index].id === val ? index : -1;
}

// find index of element with desired id.
var index = search(array, 30);

一旦我們知道索引,我們只需選擇索引之前/之后的元素:

var rangeMin = index - 10; // Inclusive. 10 is the maximum number of elements you want to render.
var rangeMax = index; // Not inclusive.

if (rangeMin < 0) { rangeMin = 0; }
if (rangeMax > array.length) { rangeMax = array.length; }

var elementsToRender = array.slice(rangeMin, rangeMax);

elementsToRender現在將包含您要渲染的所有元素。

現在讓我們說這個函數返回的項是Id為30到39的項。用戶向上滾動並希望看到30之前的消息。那么如何過濾AllMessages()返回的整個數組來獲得10 30條消息之前的最后一項?

(...)我的觀點應該顯示項目20至39

假設allMessages包含所有消息(非常大的數組)。
假設ctrl是一個控制器實例
假設ctrl.messages包含當前顯示的項目。
假設currentIndex為30
假設stepSize為10
然后,以下代碼將messages擴展為包含項目20到39,並將currentIndex設置為20:

currentIndex -= stepSize; // the new first message will have index 20
var extraItems = allMessages.slice(currentIndex, currentIndex+stepSize);
Array.prototype.push.apply(extraItems, ctrl.messages); // append ctrl.messages to extraItems
ctrl.messages = extraItems;

有關Array.prototype.push.apply更多信息,請參閱Mozilla (向下滾動到'合並兩個數組')。

這是一個小應用程序來演示它(你必須添加邏輯來保護用戶跨越數組邊界):

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
    <script>
        var myApp = angular.module('myApp', []);

        myApp.controller('MyController', function() {
            var ctrl = this;
            var allMessages = Database.AllMessages();
            var stepSize = 10;
            var currentIndex = allMessages.length - stepSize;

            // show the last 10 messages
            ctrl.messages = allMessages.length > 10 ? allMessages.slice(-10) : allMessages;

            // show ten more messages
            ctrl.showMore = function () {
                currentIndex -= stepSize;
                var extraItems = allMessages.slice(currentIndex, currentIndex+stepSize);
                Array.prototype.push.apply(extraItems, ctrl.messages);
                ctrl.messages = extraItems;
            };
        });
    </script>
</head>
<body ng-app="myApp">

<div ng-controller="MyController as ctrl">
    <table>
        <tr ng-repeat="message in ctrl.messages"><td>{{message.text}}</td></tr>
    </table>
    <button ng-click="ctrl.showMore();">show more</button>
</div>
</body>
</html>

您可以嘗試使用以下代碼獲取id為30的對象而不使用循環:

var array = [
        { id : 1, text: "First"},
        { id : 2, text: "Second"},
        { id : 3, text: "Third"},
        { id : 4, text: "Forth"},
        { id : 5, text: "Fifth"},
        { id : 6, text: "Sixth"},
        { id : 7, text: "Seventh"}
    ];  

    var result = $.grep(array, function(e){ return e.id == 5; });
    console.log(result);

在id為30的對象之前選擇最后10個項目的最佳方法是什么?

var index = 30;
var count = 10;
// 10 items before 30 :
array.slice(index-count, index);

我知道我做的這件事對某人有幫助。 這是相關的部分:

$('button.getResult').on('click', function(e) {
  e.preventDefault();
  var limit = $('input.getResult').val();
  if (limit != '' && !isNaN(limit)) {
    var dots = $('ul li');
    if (dots.length > limit) {
      //show the limit as group
      var foundSelected = false;
      var counter = 0;
      for (var i = dots.length - 1; i >= 0; i--) {

        dots.eq(i).addClass('group');
        dots.eq(i + parseInt(limit)).removeClass('group');
        counter++;
        if (i == $('li.selected').index()) {
          foundSelected = true;
        };
        if (foundSelected && counter >= limit) {
          i = -1;
        };

      };
    } else {
      //show all as group
      dots.addClass('group');
    };
  };
  return false;
});

dots基本上就是你的數組,第一個條件就是檢查以確保你想要的結果數小於數組的長度。 然后通過數組執行循環(在我的情況下向后)檢查重要項目。 如果我找到它,我將布爾值更改為true。

另外,我將每個標記為我迭代時選擇的,如果所選索引超出了分頁限制,則刪除所選標記(以保持分頁)。 一旦我找到了重要的項目並且標記了重要項目之后的正確項目數量,我就會停止循環。

當然,您可能無法在您的案例中標記事物,但我認為您可以從中獲得一些靈感。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM