编辑 - 替换了以前的解决方案,因为它没有在所有ul
标签中重复
<ul>
我已经更新了你的代码,现在它总是在所有标签中添加每个类至少两次。
我确实需要事先知道物品的总数。目前我已经将该计数添加为一个常量totalCount
,因为我不想为了获得总计数而对 JSON 对象进行两次迭代,并且我想让主代码首先工作。
也许总计数可以作为 JSON 对象的一部分作为对象根中的单独属性向下发送?
无论哪种方式,都必须以某种方式预先知道项目的总数。
我将一些必需的变量移到了更全局的范围内,因为每个 .render 方法都被调用了ul
。
var classes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'];
//var classes = ['a', 'd', 'f'];
var sourceClasses = [];
var totalCount = 6;
var selectedClasses = [];
Menu.prototype.render = function() {
// Get total item count between all arrays
//debugger;
var ul = $("<ul />");
$.each(this.data, function(i, e) {
var li = $("<li />");
//console.log(listItemCount);
//debugger;
$.each(e, function(j, f) {
//debugger;
// If we have no more classes left we re-set the list of items to the original source
// SourceClasses.length will off course not be 0 ever if we already passed the half-way mark.
if(sourceClasses.length === 0){
for(index = 0; index < classes.length; index++){
sourceClasses.push(classes[index]);
}
}
var randomClass;
randomClass = Math.round(Math.random() * (sourceClasses.length - 1) + 0);
var selectedClass = sourceClasses[randomClass];
li.append($("<a></a>", {
href: f.url,
text: f.title,
class: selectedClass
}));
sourceClasses.splice(sourceClasses.indexOf(selectedClass), 1);
selectedClasses.push(selectedClass);
// Check for half-way mark.
var itemCount = selectedClasses.length;
if (totalCount % 2 != 0) {
if (itemCount === (totalCount - 1) / 2) {
sourceClasses = selectedClasses;
var additionalClass = Math.round(Math.random() * (sourceClasses.length - 1) + 0);
sourceClasses.push(sourceClasses[additionalClass]);
selectedClasses = [];
};
} else {
if (itemCount === totalCount / 2) {
sourceClasses = selectedClasses;
selectedClasses = [];
};
}
});
ul.append(li);
});
//console.log($($(ul).find("a")));
return ul;
};
演示- 每个类在所有列表项中至少使用两次
(使用浏览器中的调试器工具检查呈现的 HTML 以获取结果)
您注意到现在内部循环中发生的第一件事是,我正在检查是否还有可用的类,如果没有,我将可用类重新设置为原始列表。
仅当您的原始可用课程列表少于总项目数时,才会发生这种情况。
在每个列表项的迭代过程中,我仍然从可用类列表中删除选定的类,以确保每个类至少出现两次。
我仍在另一个数组中记录选定的类,然后在项目列表的中途使用它来重新设置可用类的数组。
如果项目总数是奇数或偶数,则该代码有效。
对于偶数个项目,我们只需通过除以 2 来测量 laf-way 标记。
对于奇数个项目,我确保在中途标记(totalCount -1) / 2
,然后将一个随机类添加到已经选择的类作为额外的可用类.
这一切现在都应该按预期工作......
编辑(2021 年 9 月 3 日)
我检查了代码,其中有一个逻辑错误。itemCount
中途标记后重新设置。
这段代码:
var itemCount = selectedClasses.length;
假设是: // 将声明移到外部范围,现在稳步增加计数。项目计数 += 1
现在代码正在按照我的计划执行所有操作。
演示- 使用 70 个链接和 11 个类池
所有链接都获得了类,并且所有类都至少使用了两次,因为我们只有 11 个。任何链接都不应该最终没有类,因为总是有一个来源可供选择。
关于您关于确保每个班级至少使用一个的问题。这取决于可用类别与总项目的中途标记的比率。
如果您使用 11 个类作为可能的源和至少 22 个预期链接,则您的所有类都将被使用并将被使用两次。
如果您使用 20 个类和 22 个项目,则并非并非所有类都将被使用。原因是您原来的要求to use each selected class at least twice
。
为了确保所有选定的类至少使用两次,我将每个选择记录在一个名为selectedClasses
. 我们已经处理了一半可能的项目,我用选定的类数组替换源类。现在,另一半项目只能从已选择的类别列表中进行选择,从而确保每个类别至少使用两次。
想一想,如果您有一个包含 20 个类和总共 22 个项目的数组,那么如果您同时希望确保每个已选择的类至少使用两次,那么您至少不能使用所有类。这些要求相互矛盾。
可用类的数量必须小于或等于项目总数的一半,以确保所有类至少使用一个,并且所有选定的类至少使用两次。
我希望这是有道理的,但是如果您遇到困难,请随时在评论部分开始聊天,我可以再次与您查看代码,没问题。