javascript - 如何排序对象? (画家算法)

标签 javascript algorithm sorting topological-sort

所以我得到了 4 个矩形形状,我正在尝试应用排序算法 (painters algorithm) 来了解哪些形状(在 3d 中)我需要先绘制,哪些在后绘制。

注意:相机在右下角:

正确的顺序是:purple, red, blue, green(对于绘图当然是颠倒的顺序)。

img


所以我实现了一个算法,它创建了这样的东西: 每个对象都列出了正确的后继者和前任

ITEM:  red
  predecessor: -
  successor: -
ITEM:  green
  predecessor: -
  successor: red
ITEM:  blue
  predecessor: green
  successor: red
ITEM:  purple
  predecessor: blue, green
  successor: blue, red

如何根据上述信息对项目进行排序以获得正确的顺序?非常感谢任何帮助。

let digraph = {
  red: {
    predecessor: [],
    successor: []
  },
  green: {
    predecessor: [],
    successor: ["red"]
  },
  blue: {
    predecessor: ["green"],
    successor: ["red"]
  },
  purple: {
    predecessor: ["blue", "green"],
    successor: ["blue", "red"]
  }
}

let itinerary = {}
for (let e of Object.keys(digraph)) {
  if (digraph[e].successor.length != 0) itinerary[e] = digraph[e]
}

//console.log(itinerary)
let sorted_pile = []
let overflow = 0;
while (Object.keys(itinerary).length) {
  overflow++;
  if (overflow > 40) {
    console.error("OVERFLOW");
    break;
  }
  let key = Object.keys(itinerary)[0],
    entity = itinerary[key];
  delete itinerary[key];
  sorted_pile.push(key)
  let successors = digraph[key].successor
  for (succ of successors) {
    digraph[succ].predecessor = digraph[succ].predecessor.filter(function(item) {
      return item !== key;
    })
    if (digraph[succ].predecessor.length === 0) itinerary[key] = digraph[succ]
  }
}

console.log(sorted_pile)

编辑:

let tile_entities = [
    {x: 8, y: 0, w: 1, h: 5, id: "rot"},
    {x: 5, y: 0, w: 2, h: 1, id: "gruen"},
    {x: 7, y: 0, w: 1, h: 1, id: "blau"},
    {x: 4, y: 5, w: 4, h: 2, id: "lila"},
]

最佳答案

我认为这可以满足您的要求,但我从您输入的更改版本开始。转换它很容易,但您可以直接从当前流程生成此输入。 (请注意,不需要 successor 信息,因为它可以从 predecessors 派生)

const isEmpty = arr => arr.length == 0 
const removeIndex = (n, arr) => arr.slice(0, n).concat(arr.slice(n + 1))

const sortDigraph = (
  digraph, 
  sorted = [], 
  idx = digraph.findIndex(node => isEmpty(node.predecessor)),
  nodeName = (digraph[idx] || {}).name
) => isEmpty(digraph)
  ? sorted
  : sortDigraph(
    removeIndex(idx, digraph).map(({name, predecessor}) => ({
      name,
      predecessor: predecessor.filter(n => n !== nodeName)
    }), digraph),
    sorted.concat(nodeName)
  )
  
let digraph = [
  {name: 'blue', predecessor: ["green"]},
  {name: 'green', predecessor: []},
  {name: 'orange', predecessor: ["green"]},
  {name: 'purple', predecessor: ["blue", "green"]},
  {name: 'red', predecessor: ["yellow"]},
  {name: 'yellow', predecessor: ["green", "orange"]},
]

console.log(sortDigraph(digraph))

基本思想是,您可以从任何没有前任的链接开始,然后从其他链接中删除任何指向它的前任链接,并重复该过程。只要您的图形是非循环的,这就应该可以正常工作。如果您必须处理 Painter 算法的更复杂情况,那么在尝试此操作之前您将需要拆分节点。

关于javascript - 如何排序对象? (画家算法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54408175/

相关文章:

javascript - 为什么 Javascript 返回不同分辨率的设备显示?

Javascript 使用 JSON 将对象推送到 cookie

algorithm - Scala 流方法 takeWhile

c - K&R qsort理解

arrays - 根据特定元素对 SKSpriteNode 数组进行排序

javascript - 使用 React Native 对电话联系人进行排序

javascript在数组中发出 undefined variable

javascript - 如何使用 .change() 仅检查页面的一部分

algorithm - 如何存储集合,快速找到相似的模式?

c - 3D 骰子生成算法