使用上下文找到Array.sort的方向

时间:2018-12-16 01:17:16

标签: javascript arrays sorting mergesort

鉴于其排序值,我想找到一个方向。但是,我发现仅index不能完成我想要的事情。

考虑到排序功能,我只想确定某项是否已根据其值实际移至其他索引,而不是因为另一项已移动。

示例:

const things = [
  { id: 't1', val: 4 }, // This moves to index 1, see T1 notes
  { id: 't2', val: 2 },
  { id: 't3', val: 5 }, // This moves to index 0
  { id: 't4', val: 1 },
  { id: 't5', val: 3 },
]

// Sort to highest vals first
let thingOrder = things.sort((a, b) => b.val - a.val)

thingOrder = thingOrder.map((thing, index) => {
  const oldIndex = things.indexOf(thing)

  if (index === oldIndex)
    thing.direction = 'same'
  else if (index > oldIndex)
    thing.direction = 'up'
  else if (index < oldIndex)
    thing.direction = 'down'

  return thing
})

console.log(thingOrder)

预期结果:

{ id: 't3', val: 5 }, // Up
{ id: 't1', val: 4 }, // Same
{ id: 't5', val: 3 }, // Same
{ id: 't2', val: 2 }, // Down
{ id: 't4', val: 1 }, // Down

T1注意:从技术上讲,标识为t1的项目已移至索引1,但这并不是因为它是val-而是因为T3已移至其上方。

我如何实现发现某项在列表中是否真正上移或下移的目标?

2 个答案:

答案 0 :(得分:2)

根据评论,似乎有一些关于移动的含义的讨论。我不确定这是什么意思(即使在评论之后)

  

考虑到排序功能,我只想根据其值确定某项是否实际上已移至其他索引,而不是因为另一项已移动

一个项目不会根据其值移动。它是根据其价值与周围人们的关系而移动的。

但是,如果您只是想比较项目从何处开始,您可以这样做。 使范围从零到数组的长度。然后根据数组的排序顺序对其进行排序。排序后的范围将向您显示在哪里索引。

const things = [
    { id: 't1', val: 4 }, // This moves to index 1, see T1 notes
    { id: 't2', val: 2 },
    { id: 't3', val: 5 }, // This moves to index 0
    { id: 't4', val: 1 },
    { id: 't5', val: 3 },
  ]

// This is a simple range:
let sortOrder = Array.from(things, (_, i) => i)

// Sort it based on things
sortOrder.sort((a, b) => things[a].val - things[b].val )

console.log("sort order:", sortOrder)

// map to direction names
// by comparing index to current position
let directions = sortOrder.map((item, i) => {
    if (item > i) return "up"
    if (item < i) return "down"
    return "same"
})

console.log(directions)

答案 1 :(得分:0)

尽管Mark的回答有所帮助,但这并不能使我到那里。我想查看一个项目相对于其他项目是向上还是向下移动。

我最终得到的解决方案是:

const things = [
  { id: 't1', val: 4 }, // Expected: Same
  { id: 't2', val: 2 }, // Expected: Down
  { id: 't3', val: 5 }, // Expected: Up
  { id: 't4', val: 1 }, // Expected: Down
  { id: 't5', val: 3 }, // Expected: Same
]

let thingOrder = things.slice().sort((a, b) => b.val - a.val)

indexDiff = (thing, oldIndex) => {
 const newIndex = thingOrder.indexOf(thing)
 const indexDiff = oldIndex - newIndex

 return indexDiff
}

thingOrder = things.map((thing, oldIndex) => { 
  const indexDiffVal = indexDiff(thing, oldIndex)

  const targetIndexDiff = indexDiff(
    thingOrder[oldIndex],
    things.indexOf(thingOrder[oldIndex]
  ))

  const moveDistance = indexDiffVal + targetIndexDiff
  const moveDirectionSign = Math.sign(moveDistance)

  let moveDirection = 
        (moveDirectionSign === 1) ? 'up'
        : (moveDirectionSign === -1) ? 'down' 
        : (moveDirectionSign === 0) ? 'same'
        : (moveDirectionSign === -0) ? 'same'
        : 'same'

  moveDirection = (moveDistance === 1) ? 'same' : moveDirection

  thing.direction = moveDirection

  return thing
})

console.log(thingOrder)

这些是我试图弄清楚该公式时要注意的事项。

indexDiff:
t1 = 1i - 2i = -1d (down)
t2 = 2i - 4i = -2d (down)
t3 = 3i - 1i = 2d (up)
t4 = 4i - 5i = -1d (down)
t5 = 5i - 3i = 2d (up)

Compare diffs of item[newIndex] to item[oldIndex]
t1 = oldIndex = 1, t3 = newIndex = 1
t1 = indexDiff(-1), t3 = indexDiff(2)
-1 + 2 = [1] (didn't really move)

t2 = oldIndex = 2, t1 = newIndex = 2
t2 = indexDiff(-2), t1 = indexDiff(-1)
-2 + -1 = [-3] (did move down)

t3 = oldIndex = 3, t5 = newIndex = 3
t3 = indexDiff(2), t5 = indexDiff(2)
2 + 2 = [4] (did move up)

t4 = oldIndex = 4, t2 = newIndex = 4
t4 = indexDiff(-1), t2 = indexDiff(-2)
-1 + -2 = [-3] (did move down)

t5 = oldIndex = 5, t4 = newIndex = 5
t5 = indexDiff(2), t4 = indexDiff(-1)
2 + -1 = [1] (didn't really move)