![](/img/trans.png)
[英]How to get array of objects by object and arrays in javascript
[英]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为30
到39
。 现在用户希望在30
之前看到这些项目。 在id为30
对象之前选择最后10个项目的最佳方法是什么? 如前所述,阵列的大小很大,所以性能在这里很重要。
上面的例子只是一个例子。 我应该能够根据需要一次多次过滤我的数组10个项目。
我想要实现的是加载一个大阵列,但不是一次性加载。 我想一次加载10个项目。 我正在跟踪我的过滤数组中的第一个对象(例如30
),然后我想在该特定对象之前获取最后10个对象。
这是我的观点:
<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为30
到39
。 用户向上滚动并希望在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.