按选择优先排序的高性能方式

More performant way of sorting by selected first

本文关键字:高性能 方式 排序 选择      更新时间:2023-09-26

我上面有一个表格和一张地图,其中包含与下面的表格行相关的标记。当用户在上面的地图上选择项目时,它会突出显示匹配的行,然后将这些行移动到表的顶部,但按用户的排序设置进行排序。

例如,如果您有以下原始数据(未显示数据(:

[
  {id: 1, name: 'Z'},
  {id: 2, name: 'Y'},
  {id: 3, name: 'X'},
  {id: 4, name: 'W'}
]

然后,用户在地图上选择id: 1id: 3,并按name排序。数据变为:

[
  {id: 3, name: 'X'}, // selected
  {id: 1, name: 'Z'}, // selected
  {id: 4, name: 'W'}, // not selected
  {id: 2, name: 'Y'}  // not selected
]

有一些数据集有 10,000+ 行,我担心当他们选择项目时,由于 2 个过滤器 + concat,这锁定时间太长。有没有办法一次性执行此操作,或者只是一种方法可以防止浏览器在执行此操作时锁定?

  var selectedRows = rows.filter(function (row) {
    return selectedMarkerIds.indexOf(row.id) !== -1
  });
  var nonSelectedRows = rows.filter(function (row) {
    return selectedMarkerIds.indexOf(row.id) == -1
  });
  var allRows = selectedRows.concat(nonSelectedRows);
  myTable.updateRowSort(allRows);

尝试减少。在回调函数中,它检查是否选择了该行,并将其推送到结果对象中的相应数组。您只需一次完成此操作,然后在最后一步中连接数组。

var result = rows.reduce((result, row) => {
  selectedMarkerIds.indexOf(row.id) !== -1 ? result.selected.push(row) : result.notSelected.push(row);
  return result;
}, {
  selected: [],
  notSelected: []
});
result.selected.concat(result.notSelected);

我也是 lodash 的忠实粉丝,这里是 lodash 实现。我首先将数组传递给链函数,该函数基本上将其包裹在 lodash 包装器周围,该包装器支持链接 lodash 函数。然后我通过我的reduce函数传递数组,类似于我上面对Array.prototype.reduce所做的,但这次结果的初始值是一个由两个数组组成的数组:第一个数组用于选定的行,而第二个数组用于非选定的行。然后,我使用 _.flatten 来展平嵌套数组,因此现在我们有一个对象数组而不是数组数组。我调用 value 来解开 lodash 包装器并获取我的 final 值,它是一个行数组。

/**
 * in the reduce function, the initial value of the 
 * result is an array of two arrays. 
 * the first array is for selected items.
 * the second array is for non-selected items.
 */
var newArray = _.chain(rows)
  .reduce((result, row) => {
    selectedMarkerIds.indexOf(row.id) !== -1 ? result[0].push(row) : result[1].push(row);
    return result;
  }, [ [], [] ])
  .flatten()
  .value();
与其在

每次用户更新时都重新排序,不如保留两个持久数组。一个用于所选项目,一个用于未选择的项目。当用户选择一个项目时,将其拼接出未选择的项目数组,然后将其推送到所选项目数组中。然后通过连接这两个数组来更新最终数组。

你最终可能会得到类似的东西:

  var selectedItem = nonSelectedItems.splice(selectedItemIndex, 1);
  selectedItems.push(selectedItem);
  var allRows = selectedRows.concat(nonSelectedRows);
  myTable.updateRowSort(allRows);

。其中 selectedItems 和非 SelectedItems 是存在于任何事件处理程序的作用域之外的数组,这些事件处理程序是在用户选择某些内容时更新顺序而调用的

每次选择时再使用一个变量 selected-index = 0 - 增量。使用unshift推送@top过滤器或使用拼接推送@selected-index,如果要使用排序位置迭代0 to selected-index并使用splice推送

要保留原始索引,您需要向每条记录添加 .index 属性:

var indexed = rs.map( function(el,index) { el.index = index; return el; } );

然后排序是微不足道的:

var sorted = indexed.sort(function(a,b) {
  var asel = selectedMarkerIds.indexOf(a.id) !== -1;
  var bsel = selectedMarkerIds.indexOf(b.id) !== -1; 
  if( asel && bsel )
    return a.name < b.name ? -1:1;
  if( asel ) return -1;
  if( bsel ) return +1;
  // both records are in not selected set
  return a.index - b.index;
});