【问题标题】:Javascript order div's by data value highest firstJavascript按数据值排序div,首先是最高的
【发布时间】:2017-05-12 21:17:51
【问题描述】:

我有这个代码。如果你看数据,id就是div的id。 接下来是悬停字段,每个字段都有一个数字值。

以下代码将在每次悬停 div 时增加悬停次数。

var counter = [
    {id: 1, hovers: 1},
    {id: 2, hovers: 0},
    {id: 3, hovers: 8},
    {id: 4, hovers: 5},
    {id: 5, hovers: 3},
    {id: 6, hovers: 4},
    {id: 7, hovers: 2},
    {id: 8, hovers: 9},
    {id: 9, hovers: 2}
]

$('div').mouseover(function() {
  var obj = counter.find(e => e.id == $(this).attr('id'))
  if(obj) obj.hovers++
  console.log(obj)
})

这里是被悬停和计数器的 html div。

<div id="1"><p>Box 1</p></div>
<div id="2"><p>Box 2</p></div>
<div id="3"><p>Box 3</p></div>
<div id="4"><p>Box 4</p></div>
<div id="5"><p>Box 5</p></div>
<div id="6"><p>Box 6</p></div>
<div id="7"><p>Box 7</p></div>
<div id="8"><p>Box 8</p></div>
<div id="9"><p>Box 9</p></div>

如果我们查看计数器数据。

如何移动 div 以使悬停次数最多的 div 排在最前面,然后按顺序与其他 div 一起移动?

【问题讨论】:

  • 所以你希望它在每次悬停时重新排序?
  • 不,那太多了。也许在单击按钮时重新排序?
  • 您可以考虑使用 flexbox 进行重新排序:flex-direction: &lt;axis&gt;-reverse,例如flex-direction: column-reverse 并将每个 div 的 order 属性设置为检测到的悬停事件数。

标签: javascript jquery ecmascript-6


【解决方案1】:

所以你想要做的实际上是非常昂贵的。使用您当前的数据结构,您必须在每次鼠标悬停时对 counter 数组进行排序以保持正确的顺序。这意味着,如果您在counter 中有N 鼠标悬停和M 项,则此操作的时间复杂度将为O(N*MlogM)

每次发生悬停时搜索数组也有很好的效果。

假设您需要此排序列表的频率远低于悬停次数,您可以在需要时进行排序,而不是每次悬停时进行排序。

此外,您可以将数据保存在 Map&lt;id, hoverCount&gt; 而不是数组中,以使悬停更新成为一个恒定时间操作。这也允许使用任何 JS 值作为 id 而不仅仅是数字。

const counter = new Map([
  [1, 1],
  [2, 0],
  [3, 8],
  [4, 5],
  [5, 3],
  [6, 4],
  [7, 2],
  [8, 9],
  [9, 2]
]);

$('div').mouseover(function() {
  const id = Number($(this).attr('id'));
  if (counter.has(id)) {
    counter.set(id, counter.get(id) + 1);
  }
});

如果您知道您的 id 将匹配索引值 - 每个元素都为 1,就像现在一样,那么就不需要映射也不需要遍历数组,只需使用 id 作为即时索引访问:

$('div').mouseover(function() {
  const idx = Number($(this).attr('id')) - 1;
  if (idx >= 0 && idx < counter.length) {
    counter[idx].hovers += 1;
  }
});

就排序而言,只需比较每个元素的hovers 属性即可:

// sorting the Map
getSorted() {
  return [...counter.entries()].sort((a, b) => b[1] - a[1]);
}

// sorting the array of <id, hovers> objects
getSorted() {
  return counter.sort((a, b) => b.hovers - a.hovers));
}

【讨论】:

  • 请注意,这个排序函数不会给你数组的降序,但是这个会:counter.sort((a, b) =&gt; b.hovers - a.hovers)
【解决方案2】:

这是一个有趣的任务,这是我的解决方案:

(注意我使用click 事件来查看更可控的操作;将事件更改为您需要的任何内容)

当您单击一个元素时,计数器会增加,并且所有元素都会相应地重新排序。最高值位于顶部(如果需要,请在 sort 函数内更改)。

const els = document.querySelectorAll('div');

const counter = [
    {id: 1, hovers: 1},
    {id: 2, hovers: 0},
    {id: 3, hovers: 8},
    {id: 4, hovers: 5},
    {id: 5, hovers: 3},
    {id: 6, hovers: 4},
    {id: 7, hovers: 2},
    {id: 8, hovers: 9},
    {id: 9, hovers: 2}
];

const cMap = new Map(); // create a map for convenience
for (const el of counter) {
  cMap.set(el.id, el.hovers);
}

for (const el of els) {
  el.addEventListener('click', function() { // change event to a different one if needed
    const id = parseInt(el.id);
    cMap.set(id, cMap.get(id) + 1);
    el.innerHTML = '<p>Box ' + id + '; hovers: ' + cMap.get(id) + '</p>';

    const sortedIds = [...new Map([...cMap.entries()].sort((a, b) => b[1] - a[1])).keys()];
   
    const b = document.body;
    while (b.firstChild) { b.removeChild(b.firstChild); }; // clear body
    for (const i of sortedIds) {
      for (const el of els) { if (el.id == i) b.appendChild(el); } // append divs in order
    }
  })
}
<div id="1"><p>Box 1</p></div>
<div id="2"><p>Box 2</p></div>
<div id="3"><p>Box 3</p></div>
<div id="4"><p>Box 4</p></div>
<div id="5"><p>Box 5</p></div>
<div id="6"><p>Box 6</p></div>
<div id="7"><p>Box 7</p></div>
<div id="8"><p>Box 8</p></div>
<div id="9"><p>Box 9</p></div>

【讨论】:

    猜你喜欢
    • 2012-03-19
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 2012-12-15
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多