比方说,我有一些物品,每个物品都有一个序列-较少的序列表示物品在上面。一个项目可以对其他项目具有依赖性。同样,一个项目可以具有可信赖的对象-即其他一些项目可能依赖于它。下面的项目列表(我在这里使用了关联的数组)列出了项目-每个项目的属性“ dep”列出了依赖项和可靠项。
var dependencyDict = {
item1: {dependsOn: [], dependable: ['item3']},
item2: {dependsOn: [], dependable: []},
item3: {dependsOn: ['item1'], dependable: ['item4']},
item4: {dependsOn: ['item3'], dependable: []}
}
var itemList = {
item1: {
name: 'item1',
seq: 1,
dep: dependencyDict['item1']
},
item2: {
name: 'item2',
seq: 2,
dep: dependencyDict['item2']
},
item3: {
name: 'item3',
seq: 3,
dep: dependencyDict['item3']
},
item4: {
name: 'item4',
seq: 4,
dep: dependencyDict['item4']
}
}
根据上述内容,项目按其顺序依次为:
item1
item2
item3
item4
我的目标是对项目进行重新排序,即更改顺序(如果可能的话),以使依存关系保持完整。
验证:只有在依存关系保持不变的情况下,项目才能移动:即
一个项目只能依赖于其上方的项目,即其顺序小于该项目的顺序 反之亦然
一个项目只有当项目低于项目时,即项目的顺序大于项目的顺序,才可以将项目作为从属项
例如,如果我说move(item3,2)-我要将item3移至位置2,以便新项目列表应为:
{
item1: {
name: 'item1',
seq: 1,
dep: dependencyDict['item1']
},
item2: {
name: 'item2',
seq: 3,
dep: dependencyDict['item2']
},
item3: {
name: 'item3',
seq: 2,
dep: dependencyDict['item3']
},
item4: {
name: 'item4',
seq: 4,
dep: dependencyDict['item4']
}
请注意序列的更改
但是,如果我说move(item3,1),它将不会,因为item3依赖于item1-如果它移至位置1,则item1将移至位置2,这使该项只能依赖于项的规则无效在它上面。
我的代码处于正常工作状态,但是我使用的if-elses比合适的算法还要多
灵活性:项目列表可以放在任何数据结构中,可以使用任何算法
答案 0 :(得分:1)
一些建议:
Set
来注册依赖性而不是数组可能会更有效。 dependsOn
或dependable
中的一个,因为一个可以从另一个中派生seq
,而仅依赖项在数组中的索引。确实,这意味着您必须使用indexOf
扫描阵列,但是另一方面,您不必对移动中涉及的所有seq
属性进行更新。这是我建议的数据结构的class
实现。
class OrderedGraph {
constructor(pairs) {
this._dep = new Map;
this._order = [];
if (pairs) for (let [item, dependsOn] of pairs) this.add(item, dependsOn);
}
add(item, dependsOn=[]) {
for (let ref of dependsOn) if (!this._dep.has(ref)) throw ref + " not found";
this._dep.set(item, new Set(dependsOn));
this._order.push(item);
}
move(item, toIdx) {
let fromIdx = typeof item === "number" ? item : this._order.indexOf(item);
if (fromIdx < 0) throw "not found: " + item
if (typeof item === "number") item = this._order[item];
let dep = this._dep.get(item);
let ok = fromIdx > toIdx
? !this._order.slice(toIdx, fromIdx).some(it => dep.has(it))
: !this._order.slice(fromIdx+1, toIdx+1).some(it => this._dep.get(it).has(item));
if (ok) this._order.splice(toIdx, 0, ...this._order.splice(fromIdx, 1));
return ok;
}
indexOf(item) { return this._order.indexOf(item) }
includes(item) { return this._dep.has(item) }
* values() { yield * this._order }
[Symbol.iterator]() { return this.values() }
}
// Example use
let data = new OrderedGraph([
["item1", []],
["item2", []],
["item3", ["item1"]],
["item4", ["item3"]]
]);
// Some actions on the data object:
console.log(JSON.stringify(Array.from(data)));
console.log("success moving 'item3' to 0? ", data.move("item3", 0));
console.log(JSON.stringify(Array.from(data)));
console.log("success moving 'item3' to 1? ", data.move("item3", 1));
console.log(JSON.stringify(Array.from(data)));
console.log("success moving 'item3' to 1? ", data.move("item3", 1));
console.log(JSON.stringify(Array.from(data)));
console.log("success moving 'item3' to 2? ", data.move("item3", 2));
console.log(JSON.stringify(Array.from(data)));
console.log("index of 'item3': ", data.indexOf("item3"));
答案 1 :(得分:0)
您可以使用所需的新节点列表的索引来检查依赖项。
function move(node, position) {
var nodes = Object.keys(itemList).sort(({ seq: a }, { seq: b }) => a - b);
nodes.splice(position - 1, 0, ...nodes.splice(itemList[node].seq - 1, 1));
var valid = nodes.every((n, i) =>
dependencyDict[n].dependsOn.every(m => nodes.indexOf(m) <= i) &&
dependencyDict[n].dependable.every(m => nodes.indexOf(m) >= i)
);
console.log(valid);
if (valid) nodes.forEach((node, i) => itemList[node].seq = i + 1);
console.log(nodes);
console.log(itemList);
}
var dependencyDict = {
item1: {dependsOn: [], dependable: ['item3']},
item2: {dependsOn: [], dependable: []},
item3: {dependsOn: ['item1'], dependable: ['item4']},
item4: {dependsOn: ['item4'], dependable: []}
},
itemList = {
item1: { name: 'item1', seq: 1, dep: dependencyDict['item1'] },
item2: { name: 'item2', seq: 2, dep: dependencyDict['item2'] },
item3: { name: 'item3', seq: 3, dep: dependencyDict['item3'] },
item4: { name: 'item4', seq: 4, dep: dependencyDict['item4'] }
};
move('item3', 1);
move('item3', 2);
.as-console-wrapper { max-height: 100% !important; top: 0; }