JavaScript 最佳实践通过三个因素过滤数组

标签 javascript arrays filter reduce

我正在根据以下条件过滤一系列 Vet 交易:

  • 对于一小时内的每笔交易,仅将最昂贵的交易放入结果中(交易为 {dog, timestamp, amount})
  • 如果一小时内有多笔交易具有相同的狗领带且最昂贵的交易,则仅将最早的交易放入结果中
  • 如果在整个交易数组中某只狗的交易超过 10 笔,则不要在结果中包含该狗的任何交易

一小时时段为 00:00:00 - 00:59:59、01:00:00 - 01:59:59 等。

在降低复杂性的同时,我想提出一个遵循最佳实践的更易于阅读的解决方案。这是数据(已按时间排序):

const dogs = [
  { "dog":"ralph", "timestamp":"2/23/2020 03:04:57", "amount": 140.00 },
  { "dog":"toto", "timestamp":"2/23/2020 03:14:31", "amount": 130.00 },
  { "dog":"toto", "timestamp":"2/23/2020 03:15:10", "amount": 145.00 },
  { "dog":"sadie", "timestamp":"2/23/2020 03:15:53", "amount": 175.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 04:05:44", "amount": 220.00 },
  { "dog":"sadie", "timestamp":"2/23/2020 05:34:41", "amount": 100.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 05:39:11", "amount": 40.00 },
  { "dog":"toto", "timestamp":"2/23/2020 05:43:00", "amount": 240.00 },
  { "dog":"toto", "timestamp":"2/23/2020 05:59:58", "amount": 235.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 06:11:52", "amount": 20.00 },
  { "dog":"toto", "timestamp":"2/23/2020 06:12:53", "amount": 90.00 },
  { "dog":"rex", "timestamp":"2/23/2020 06:12:53", "amount": 315.00 },
  { "dog":"max", "timestamp":"2/23/2020 06:12:53", "amount": 285.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 06:13:14", "amount": 240.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 07:05:21", "amount": 60.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 08:42:50", "amount": 80.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 09:07:53", "amount": 100.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 10:07:35", "amount": 200.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 11:04:20", "amount": 120.00 },
  { "dog":"bella", "timestamp":"2/23/2020 11:04:40", "amount": 160.00 },
  { "dog":"sadie", "timestamp":"2/23/2020 11:04:54", "amount": 160.00 },
  { "dog":"bella", "timestamp":"2/23/2020 11:34:33", "amount": 160.00 },
  { "dog":"bella", "timestamp":"2/23/2020 11:44:23", "amount": 160.00 },
  { "dog":"bella", "timestamp":"2/23/2020 11:48:43", "amount": 125.00 },
  { "dog":"bella", "timestamp":"2/23/2020 12:03:53", "amount": 80.00 },
  { "dog":"bella", "timestamp":"2/23/2020 12:04:03", "amount": 100.00 },
  { "dog":"bella", "timestamp":"2/23/2020 13:11:54", "amount": 125.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 14:04:35", "amount": 160.00 },
  { "dog":"bella", "timestamp":"2/23/2020 14:21:10", "amount": 170.00 },
  { "dog":"bella", "timestamp":"2/23/2020 15:15:18", "amount": 140.00 },
  { "dog":"bella", "timestamp":"2/23/2020 16:15:20", "amount": 180.00 },
  { "dog":"ralph", "timestamp":"2/23/2020 17:49:55", "amount": 180.00 }
]

这是我的工作解决方案:

function lessThanTen(dogs) {
  let count = {}
  let results = [];
  for(let i = 0; i<dogs.length; i++) {
    count[dogs[i].dog] ? count[dogs[i].dog] +=1 : count[dogs[i].dog] = 1;
  }
  for(let i = 0; i<dogs.length; i++) {
    if(!(count[dogs[i].dog] > 10)) {
      results.push(dogs[i]);
    }
  }
  return results;
}

function mostExpensive(dogs) {
  let curHour, nextHour, prevAmount, curAmount, nextAmount, highIndex;
  let results = [];
  const filtered = lessThanTen(dogs);

  filtered.forEach((click, index) => {
    curHour = filtered[index].timestamp.split(" ")[1].substring(0,2);
    curAmount = filtered[index].amount;
    if(index > 0) {
      prevAmount = filtered[index-1].amount;
    }
    if(index < filtered.length - 1) {
      nextHour = filtered[index + 1].timestamp.split(" ")[1].substring(0,2);
      nextAmount = filtered[index + 1].amount
    }
    if ((curHour === nextHour) && ((curAmount > prevAmount && curAmount > nextAmount) || (curAmount === nextAmount && !highIndex)) ) {
      highIndex = index;
    }
    if (nextHour > curHour) {
      results.push(filtered[highIndex ? highIndex : index]);
      highIndex = null;
    }
  });
  console.log(results);
}
mostExpensive(dogs);

我是否可以/应该将“如果同一只狗在一小时内发生多笔交易”分解为它自己的函数,以便更容易测试?

有没有好的方法来清理forEach中的所有if语句?我尝试了过滤和减少,但不幸的是在比较以前和当前的数量和时间时迷失了方向。

对于少于十个函数,我应该使用除 for 循环之外的其他东西吗?这里的最佳实践是什么?我想不出一种方法来避免使用两个循环 O(2n)。有建议吗?

一般来说,实现这三个标准的最清晰、最实用的方法是什么?

最佳答案

小于十

您滥用条件运算符作为 if 语句。写出来(并使用 in 运算符检查狗是否在 count 集合中),则为:

if (dogs[i].dog in count) {
  count[dogs[i].dog] += 1;
} else {
  count[dogs[i].dog] = 1;
}

这更清楚,但可以减少重复。您可以将条件运算符用作实际运算符来检查是否存在现有值。在局部变量中获取狗的名字可以使代码更短、更具可读性:

let dog = dogs[i].dog;
count[dog] = (dog in count ? count[dog] : 0) + 1;

您可以使用数组的 filter 方法来获取狗出现十次或更少的项目,而不是在循环中将项目添加到 results 中:

dogs.filter(item => count[item.dog] <= 10)

这将使函数:

function lessThanTen(dogs) {
  let count = {};
  for (let i = 0; i < dogs.length; i++) {
    let dog = dogs[i].dog;
    count[dog] = (dog in count ? count[dog] : 0) + 1;
  }
  return dogs.filter(item => count[item.dog] <= 10);
}

最贵

我无法真正理解代码中的意图。您似乎正在将每个项目与前一个和下一个进行比较,但这并不能告诉您它是否是一小时内的最高值。此外,与可能来自不同时间的先前金额进行比较似乎是一个错误。

我用一种我希望易于理解的算法重写了该函数。它只是通过与之前的最佳项目进行比较来保留找到的最佳项目的索引。由于没有前瞻性,您将获得最后一小时的最佳项目,以添加到循环后的结果中。

function mostExpensive(dogs) {
  const filtered = lessThanTen(dogs);

  let results = [];
  let prevHour = null, highIndex = null;

  filtered.forEach((item, index) => {
    let hour = item.timestamp.split(" ")[1].substring(0,2);
    // When the hour changes
    if (prevHour !== null && hour !== prevHour) {
      // Add best item found in previous hour
      results.push(filtered[highIndex]);
      // Reset index for the new hour
      highIndex = null;
    }
    // When first item in hour, or better than previously found
    if (highIndex === null || item.amount > filtered[highIndex].amount) {
      // Keep the index of the best item
      highIndex = index;
    }
    // Keep the hour for next iteration
    prevHour = hour;

  });
  // If there is a result from the last hour
  if (highIndex !== null) {
    // Add best item found in last hour
    results.push(filtered[highIndex]);
  }
  console.log(results);
}

关于JavaScript 最佳实践通过三个因素过滤数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60364649/

相关文章:

javascript - Cube.js - 无法连接 2 个或更多表,但不断收到 "Can' t find join path to join“错误

javascript - 按钮不在选项卡之间共享操作

python - 为什么我的数组比较算法给我错误的输出?

Matlab快速邻域运算

php - yII2:日期过滤器如何在 Gridview 中

javascript - 点到线的距离 3d 公式

c - 结构体数组占用内存过多

javascript - Javascript 程序无法正常运行

php - 有没有更简洁的方法来按键值过滤?

javascript - 如何从回调函数中设置元素属性