在另一个列表中查找项目的最有效算法是什么?让我尝试写一个例子:
[{"id": 1, "skill": 10},{"id": 2, "skill": 90}];
[{"id": 12, "mood": 5},{"id": 2, "mood": 70}]
。该信息由数组表示:
[[1, 10], [2, 90]]
; [[12, 5], [2, 70]]
。在我的情况下,雇主只能与心情 低于其 的客户互动。我的职能回报应该是具有最高互动度的雇主。
我编写了可以执行此规则的函数,但是当我有大量的雇主或客户时,它的运行速度非常慢-完成过程花费了7秒钟以上。
function countEmployersByMoodAtt(operatos, customers) {
let distribution = [];
//sort operators by skill so I can guarantee that big skills won't come first
operatos.sort((a, b) => a[1] - b[1]);
operatos.forEach(cs => {
let skill = cs[1];
//map to extract only the customer id
let customersAvailable = customers
.filter(customer => customer[1] <= skill)
.map(x => x[0]);
//convert to set because i've wrote it's fast
let customerAvSet = new Set(customersAvailable);
//include on result list
distribution.push([cs[0], customersAvailable.length]);
//remove customers already assigned
customers = customers.filter(([cs]) => !customerAvSet.has(cs));
});
//sort to first position be hightest score
distribution.sort((a, b) => b[1] - a[1]);
//return operator
return distribution[0][0];
}
输入示例:
operators = [[1, 60], [3, 90]];
customers = [[1, 30], [1, 40], [1, 60], [1, 70]];
输出应为1。
主要规则:不能获得最高的操作技能并全力以赴。我需要在操作员之间保持平衡-我需要从较低的技能过渡到较高的技能。
关于如何优化它的任何提示?
谢谢。
答案 0 :(得分:1)
此功能应按O(c*o)
的顺序运行,其中c
是客户数,o
是操作员数。
var o = [[1, 60], [3, 90]];
var c = [[1, 30], [1, 40], [1, 60], [1, 70]];
function countEmployersByMoodAtt(operatos, customers) {
var cInt = [];
var gInt = {};
var i, j;
var opIndex;
for (i = 0; i < customers.length; i++) {
// find lowest possible operator to interact with
opIndex = null;
for (j = operatos.length - 1; j >= 0; j--) {
if (operatos[j][1] < customers[i][1]) {
// can't interact. continue to next operator
continue;
}
if (opIndex !== null) {
if (operatos[j][1] < operatos[opIndex][1]) {
opIndex = j;
}
} else {
opIndex = j;
}
}
if (opIndex === null) {
cInt.push(null);
} else {
cInt.push(operatos[opIndex][0]);
}
}
for (i = 0; i < cInt.length; i++) {
if (gInt[cInt[i]] === undefined) {
gInt[cInt[i]] = 0;
}
gInt[cInt[i]] += 1;
}
var maxId = null, maxOp = 0;
var keys = Object.keys(gInt);
for (i = 0; i < keys.length; i++) {
if (gInt[keys[i]] > maxOp) {
maxId = keys[i];
maxOp = gInt[keys[i]];
}
}
return maxId;
}
console.log(countEmployersByMoodAtt(o, c));
基准:
var o = [];
var c = [];
for (var k = 0; k < 10000; k++) {
o.push([k + 1, Math.floor(Math.random() * 1000000)]);
c.push([k + 1, Math.floor(Math.random() * 1000000)]);
}
function myCountEmployersByMoodAtt(operatos, customers) {
var cInt = [];
var gInt = {};
var i, j;
var opIndex;
for (i = 0; i < customers.length; i++) {
// find lowest possible operator to interact with
opIndex = null;
for (j = operatos.length - 1; j >= 0; j--) {
if (operatos[j][1] < customers[i][1]) {
// can't interact. continue to next operator
continue;
}
if (opIndex !== null) {
if (operatos[j][1] < operatos[opIndex][1]) {
opIndex = j;
}
} else {
opIndex = j;
}
}
if (opIndex === null) {
cInt.push(null);
} else {
cInt.push(operatos[opIndex][0]);
}
}
for (i = 0; i < cInt.length; i++) {
if (gInt[cInt[i]] === undefined) {
gInt[cInt[i]] = 0;
}
gInt[cInt[i]] += 1;
}
var maxId = null, maxOp = 0;
var keys = Object.keys(gInt);
for (i = 0; i < keys.length; i++) {
if (gInt[keys[i]] > maxOp) {
maxId = keys[i];
maxOp = gInt[keys[i]];
}
}
return maxId;
}
function yourCountEmployersByMoodAtt(operatos, customers) {
let distribution = [];
//sort operators by skill so I can guarantee that big skills won't come first
operatos.sort((a, b) => a[1] - b[1]);
operatos.forEach(cs => {
let skill = cs[1];
//map to extract only the customer id
let customersAvailable = customers
.filter(customer => customer[1] <= skill)
.map(x => x[0]);
//convert to set because i've wrote it's fast
let customerAvSet = new Set(customersAvailable);
//include on result list
distribution.push([cs[0], customersAvailable.length]);
//remove customers already assigned
customers = customers.filter(([cs]) => !customerAvSet.has(cs));
});
//sort to first position be hightest score
distribution.sort((a, b) => b[1] - a[1]);
//return operator
return distribution[0][0];
}
var t0 = performance.now();
console.log('MyResult: ' + myCountEmployersByMoodAtt(o, c));
var t1 = performance.now();
console.log('Your result: ' + yourCountEmployersByMoodAtt(o, c));
var t2 = performance.now();
console.log('My time: ' + (t1 - t0));
console.log('Your time: ' + (t2 - t1));
答案 1 :(得分:1)
我建议使用具有降序排序和迭代客户技能的数组,该数组迭代计数器数组并检查心情m
。
如果counter
小于技能,则增加计数,否则退出内循环。
var employers = [[1, 10], [2, 90]],
customers = [[12, 5], [2, 70]],
counter = employers.map(([, v]) => [v, 0]).sort(([a], [b]) => b - a);
customers.forEach(([m]) => counter.every(a => m < a[0] && ++a[1]));
console.log(counter);
包含每个技能级别的计数。
<select>
<option value="" disabled="disabled" selected="selected">Please select a
developer position</option>
<option value="1">Beginner</option>
<option value="2">Expert</option>
</select>
答案 2 :(得分:0)
好的,所以您的问题尚不清楚,但是通读代码就足够了。雇主可以以比他们的技能低的心情与客户互动,但是他们不能与另一个技能较低的员工也可以与之互动的客户互动。让我们解决这个问题。
对于一个过滤器来说,过滤,将结果复制到集合中,然后运行另一个过滤器以过滤掉刚刚过滤的所有内容几乎没有意义。听起来像是一团糟,对吗?它是。
相反,只需要最初与所有客户一起创建集合即可。然后运行forEach,并从技能最低的工作人员可以服务的客户集中删除客户,为您为此服务的每个客户增加一个计数器。您实际上并未随分发一起发送客户ID,因此完全保留客户ID毫无意义。
算法将如下所示: 根据技能和情绪对员工和客户进行排序。 创建一个计数器变量。 遍历客户。 对于每个客户,如果他们的心情<当前员工的技能,请增加计数器。 如果不是,请将计数与当前员工ID一起存储在分配中。然后转到下一个员工ID。
重复。实际上没有机会使用一套。我不认为他们已下令。不过,这可以很好地工作,并且您可以在排序后一次通过。
function countEmployersByMoodAtt(operators, customers) {
console.log("Sorting operators.");
operators.sort((a, b) => a[1] - b[1]);
console.log("Sorting customers");
customers.sort((a, b) => a[1] - b[1]);
console.log("Starting processing.");
let distribution = [];
let opIndex = 0;
let customersServed = 0;
let bestEmployeeID;
let mostServed = -1;
let skill = operators[opIndex][1];
for (let i = 0; i < customers.length; ++i) {
let mood = customers[i][1];
if (mood < skill)
++customersServed;
else {
// check if new record.
if (customersServed > mostServed) {
mostServed = customersServed;
bestEmployeeID = operators[opIndex][0];
customersServed = 1; // this will count toward the employee found in while() loop.
}
// find next qualified employee.
while (mood > skill && ++opIndex < operators.length) {
skill = operators[opIndex][1];
}
// no employees can serve customer.
if (opIndex >= operators.length) {
console.log("No employees skilled enough for remaining customers.")
return [bestEmployeeID, mostServed];
}
}
}
// need to do this one more time for the last set of customers.
// because 'else' case won't run if customer is served adequately.
// and if a new employee is selected for the last customer, bestEmployee won't be set.
if (customersServed > mostServed) {
mostServed = customersServed;
bestEmployeeID = operators[opIndex[0]];
}
return [bestEmployeeID, mostServed];
}