我正在执行以下操作,从树视图中获取某些节点,然后从这些节点获取文本,过滤文本以删除唯一,然后将自定义图像附加到重复节点。
为此,我必须循环4次。有一种更简单的方法吗?我担心它对大量数据的性能。
//Append duplicate item nodes with custom icon
function addRemoveForDuplicateItems() {
var treeView = $('#MyTree').data('t-TreeView li.t-item');
var myNodes = $("span.my-node", treeView);
var myNames = [];
$(myNodes).each(function () {
myNames.push($(this).text());
});
var duplicateItems = getDuplicateItems(myNames);
$(myNodes).each(function () {
if (duplicateItems.indexOf($(this).text()) > -1) {
$(this).parent().append(("<span class='remove'></span>"));
}
});
}
//Get all duplicate items removing unique ones
//Input [1,2,3,3,2,2,4,5,6,7,7,7,7] output [2,3,3,2,2,7,7,7,7]
function getDuplicateItems(myNames) {
var duplicateItems = [], itemOccurance = {};
for (var i = 0; i < myNames.length; i++) {
var dept = myNames[i];
itemOccurance[dept] = itemOccurance[dept] >= 1 ? itemOccurance[dept] + 1 : 1;
}
for (var item in itemOccurance) {
if (itemOccurance[item] > 1)
duplicateItems.push(item);
}
return duplicateItems;
}
答案 0 :(得分:0)
此代码的方法是遍历列表,使用属性名称来指示值是否在数组中。执行后,itemOccurance将包含所有名称的列表,没有重复项。
var i, dept, itemOccurance = {};
for (i = 0; i < myNames.length; i++) {
dept = myNames[i];
if (typeof itemOccurance[dept] == undefined) {
itemOccurance[dept] = true;
}
}
答案 1 :(得分:0)
如果您必须将getDuplicateItems()
作为单独的通用函数,那么第一个循环(从myNodes
到myNames
)和最后一个循环(再次迭代myNodes
来添加span
)是不可避免的。但我很好奇。根据您的代码,duplicateItems
可以只是一组!这有助于简化getDuplicateItems()
内的2个循环。 @ user2182349的答案只需要一次修改:添加return
,例如return Object.keys(itemOccurance)
。
答案 2 :(得分:0)
如果您只关注确定重复但并不特别关注确切的发生次数,那么您可以考虑重构getDuplicateItems()
函数,如下所示:
function getDuplicateItems(myNames) {
var duplicateItems = [], clonedArray = myNames.concat(), i, dept;
for(i=0;i<clonedArray.length;i+=1){
dept = clonedArray[i];
if(clonedArray.indexOf(dept) !== clonedArray.lastIndexOf(dept)){
if(duplicateItems.indexOf(dept) === -1){
duplicateItems.push(dept);
}
/* Remove duplicate found by lastIndexOf, since we've already established that it's a duplicate */
clonedArray.splice(clonedArray.lastIndexOf(dept), 1);
}
}
return duplicateItems;
}
答案 3 :(得分:0)
如果我理解正确,这里的重点只是标记重复,对吧?你应该能够通过两个更简单的过程来做到这一点:
var seen = {};
var SEEN_ONCE = 1;
var SEEN_DUPE = 2;
// First pass, build object
myNodes.each(function () {
var name = $(this).text();
var seen = seen[name];
seen[name] = seen ? SEEN_DUPE : SEEN_ONCE;
});
// Second pass, append node
myNodes.each(function () {
var name = $(this).text();
if (seen[name] === SEEN_DUPE) {
$(this).parent().append("<span class='remove'></span>");
}
});
如果您真的关心性能,请注意,迭代DOM元素比迭代内存数组更具有性能问题。与相同长度的可比阵列相比,$(myNodes).each(...)
调用可能比迭代更昂贵。通过在数组上运行第二遍并且只在必要时访问DOM节点,您可以从中获得一些效率:
var names = [];
var seen = {};
var SEEN_ONCE = 1;
var SEEN_DUPE = 2;
// First pass, build object
myNodes.each(function () {
var name = $(this).text();
var seen = seen[name];
names.push(name);
seen[name] = seen ? SEEN_DUPE : SEEN_ONCE;
});
// Second pass, append node only for dupes
names.forEach(function(name, index) {
if (seen[name] === SEEN_DUPE) {
myNodes.eq(index).parent()
.append("<span class='remove'></span>");
}
});