我需要帮助编写一个函数来对对象数组进行排序
xid
的对象都位于数组的底部xid
,这个xid也存在于根级别的其他对象中(假设B),在这种情况下B应该放在A下面示例:
带有文本“寻找在线”的对象具有
options
键,并且在第 0 个索引上,它具有带有 step
,的
xid = "1"
对象
{
type: 'radio',
text: "Looking for online",
options: [
{
text: "Yes",
step: {
text: "Select City",
xid: 1
}
},
{
text: "No"
}
]
}
现在根级别上
xid
= 1 的对象,即带有文本“选择城市”的对象应放置在第一个对象下方
{
type: 'radio',
text: "Looking for online",
options: [
{
text: "Yes",
step: {
text: "Select City",
xid: 1
}
},
{
text: "No"
}
]
},
{
type: 'radio',
text: "Select City",
xid: 1,
options: [
{
text: "Mumbai",
step: {
text: "Select Area",
xid: 2
}
},
{
text: "Delhi",
}
]
}
同样,带有
text
="选择区域"的对象具有 xid
= 2,它应该放置在第 2 个下方
{
type: 'radio',
text: "Looking for online",
options: [
{
text: "Yes",
step: {
text: "Select City",
xid: 1
}
},
{
text: "No"
}
]
},
{
type: 'radio',
text: "Select City",
xid: 1,
options: [
{
text: "Mumbai",
step: {
text: "Select Area",
xid: 2
}
},
{
text: "Delhi",
}
]
},
{
type: 'radio',
text: "Select Area",
xid: 2,
options: [
{
text: "Yes",
},
{
text: "No"
}
]
}
输入:
let array = [
{
type: 'radio',
text: "Looking for online",
options: [
{
text: "Yes",
step: {
text: "Select City",
xid: 1
}
},
{
text: "No"
}
]
},
{
type: "single",
text: "First Name",
},
{
type: "single",
text: "Last Name"
},
{
type: 'radio',
text: "Select Area",
xid: 2,
options: [
{
text: "Yes",
},
{
text: "No"
}
]
},
{
type: 'radio',
text: "Select City",
xid: 1,
options: [
{
text: "Mumbai",
step: {
text: "Select Area",
xid: 2
}
},
{
text: "Delhi",
}
]
},
]
预期输出:
let array = [
{
type: "single",
text: "First Name",
},
{
type: "single",
text: "Last Name"
},
{
type: 'radio',
text: "Looking for online",
options: [
{
text: "Yes",
step: {
text: "Select City",
xid: 1
}
},
{
text: "No"
}
]
},
{
type: 'radio',
text: "Select City",
xid: 1,
options: [
{
text: "Mumbai",
step: {
text: "Select Area",
xid: 2
}
},
{
text: "Delhi",
}
]
},
{
type: 'radio',
text: "Select Area",
xid: 2,
options: [
{
text: "Yes",
},
{
text: "No"
}
]
},
];
我尝试编写一个快速 for 循环来操作对象索引,但在一次更新多个对象的位置时它会中断
const filteredArray = [...array];
for(let index = 0; index < filteredArray?.length; index++) {
if (filteredArray[index]?.type === 'radio' && filteredArray[index].options && filteredArray[index]?.options?.length) {
const length = (filteredArray[index].options && filteredArray[index]?.options?.length) || 0;
for(let index1 = 0; index1 < length; index1++) {
const option = filteredArray[index]?.options?.[index1];
if (option && option?.step && option?.step?.xid){
const idx = array.findIndex(item => item?.xid === option?.step?.xid);
if (idx >= 0 && idx !== index + 1) {
const removedItem = array.splice(idx, 1)[0];
array.splice(index, 0, removedItem);
}
}
}
}
}
提前抱歉,因为英语不是我的第一语言,我尝试在示例部分中解释尽可能多的内容
这看起来像一个树结构,其中每个节点可能有一些选项/步骤。我将用它构建一棵树,其中孩子是相应的
[step]
。然后我将按照项目的出现顺序将其展平(深度优先搜索)。
可能还有其他你没有提供的排序要求(如果有几个“A”项?或悬空的“B”项怎么办),但这可以修改,树结构非常灵活。
函数
buildTree
和 flattenTree
几乎是不言自明的。
let arr = [{
type: 'radio',
text: "Looking for online",
options: [{
text: "Yes",
step: {
text: "Select City",
xid: 1
}
},
{
text: "No"
}
]
},
{
type: "single",
text: "First Name",
},
{
type: "single",
text: "Last Name"
},
{
type: 'radio',
text: "Select Area",
xid: 2,
options: [{
text: "Yes",
},
{
text: "No"
}
]
},
{
type: 'radio',
text: "Select City",
xid: 1,
options: [{
text: "Mumbai",
step: {
text: "Select Area",
xid: 2
}
},
{
text: "Delhi",
}
]
},
]
function buildTree(items) {
var result = []
var lookup = {}
// prepare lookup for fast access by xid
items.forEach(item => lookup[item.xid] = item);
// make all option.steps into array of children or []
items.forEach(item => {
var steps = (item.options || []).filter(item => item.step && item.step.xid).map(item => item.step.xid)
item.children = steps.map(item => lookup[item])
})
// the roots of the tree are the items without xid (A items)
items.forEach(item => {
if (!item.xid) {
result.push(item)
}
})
// items without children should come first
result.sort(function(a, b) {
return a.children.length - b.children.length
})
return result
}
function flattenTree(tree) {
const result = [];
function dfs(node) {
result.push(node);
if (node.children) {
node.children.forEach(child => dfs(child));
}
}
tree.forEach(root => dfs(root));
result.forEach (item => delete item.children)
return result;
}
var tree = buildTree(arr)
var result = flattenTree(tree)
console.log(result)
.as-console-wrapper {
min-height: 100%
}