对数组进行排序以使父项出现在子项

时间:2017-09-21 15:48:57

标签: javascript sorting

如何订购以下列表以确保子项目始终以其父项目开头?列表中的某些项目既不是子项目也不是父项目,它们应该按字母顺序与其他父级项目一起排序。

所需的输出顺序看起来像这样  [ fizz, foobar, foobar xland, the shire, frogmorton, hobbiton]

以下是我到目前为止所尝试过的代码片段,我非常肯定将代码链接在一起是一个很好的方法,因为代码可读性原因,但我遇到了一些问题与排序规则背后的逻辑。



var items = [
  {
    "_id": "Fizz"
  },
  {
    "_id": "Frogmorton",
    "parent": "The Shire"
  },
  {
    "_id": "Hobbiton",
    "parent": "The Shire"
  },
  {
    "_id": "Foobar",
    "isParent": true
  },
  {
    "_id": "Foobar Xland",
    "parent": "Foobar"
  },
  {
    "_id": "The Shire",
    "isParent": true
  }
]

var sortedArray = items
.sort(function(first, second) {
  if(first.isParent && !second.isParent) {
    return -1
  }
  else if(second.isParent && first._id != second.parent) {
    return 0
  } else {
    return 1
  }
})


console.log("sortedArray", sortedArray)




4 个答案:

答案 0 :(得分:2)

此解决方案适用于任何深度,并使用树以正确的顺序获取相关项目。



var items = [{ _id: "Fizz" }, { _id: "Frogmorton", parent: "The Shire" }, { _id: "Hobbiton", parent: "The Shire" }, { _id: "Foobar", isParent: true }, { _id: "Foobar Xland", parent: "Foobar" }, { _id: "The Shire", isParent: true }],
    tree = function (data, root) {
        var r = [], o = {};
        data.forEach(function (t) {
            var a = { i: t._id, parent: t.p, data: t };
            a.children = o[a.i] && o[a.i].children;
            o[a.i] = a;
            if (a.p === root) {
                r.push(a);
            } else {
                o[a.p] = o[a.p] || {};
                o[a.p].children = o[a.p].children || [];
                o[a.p].children.push(a);
            }
        });
        return r;
    }(items.sort(function (a, b) { return a._id.localeCompare(b._id); }), undefined),
    ordered = tree.reduce(function flat(r, o) {
        return r.concat(o.data, (o.children || []).reduce(flat, []));
    }, []);

console.log(ordered);

.as-console-wrapper { max-height: 100% !important; top: 0; }




答案 1 :(得分:2)

你可以使用这个函数,它可以处理grand-grand-grand -...- children,通过将它转换为临时树并在其中执行深度优先迭代 - 所有功能都是:< / p>

function depthFirst(items) {
    return Array.from(items.reduce( (mp, o) =>
        (mp.get(o.parent).children.push(mp.get(o._id)), mp),
        new Map([{}].concat(items).map( (o) => [o._id, { children: [], orig: o }] ))
    ), ([_, o]) =>
        (o.children.sort((a, b) => a.orig._id.localeCompare(b.orig._id)), o)
    )[0].children.reduce(function collect(acc, o) {
        return acc.concat(o.orig, o.children.reduce(collect, []))
    }, []);
}
// Sample input
var items = [{
    "_id": "Frogmorton",
    "parent": "The Shire"
}, {
    "_id": "Hobbiton",
    "parent": "The Shire"
}, {
    "_id": "Foobar",
}, {
    "_id": "Foobar Xland",
    "parent": "Foobar"
}, {
    "_id": "Fizz"
}, {
    "_id": "The Shire"
}, {
    "_id": "added grandchild",
    "parent": "Frogmorton"
}];

console.log(depthFirst(items));

答案 2 :(得分:1)

以下解决方案可行

var items = [
  
  {
    "_id": "Frogmorton",
    "parent": "The Shire"
  },
  {
    "_id": "Hobbiton",
    "parent": "The Shire"
  },
  {
    "_id": "Foobar",
    "isParent": true
  },
  {
    "_id": "Foobar Xland",
    "parent": "Foobar"
  },
  {
    "_id": "Fizz"
  },
  {
    "_id": "The Shire",
    "isParent": true
  }
]

const sortedArray = items
  .filter(item => item.isParent || !item.parent)
  .sort((a, b) => a._id.localeCompare(b._id))
  .map(parent => [parent].concat(
      items
        .filter(item => item.parent === parent._id)
        .sort((a, b) => a._id.localeCompare(b._id)))
    )
  .reduce((acc, item) => acc.concat(item), [])
  
console.log(sortedArray);

答案 3 :(得分:0)

你可以使用带有散列的闭包来拥有一个独立的方法。

&#13;
&#13;
const items = [ { _id: "Frogmorton", parent: "The Shire" }, { _id: "Hobbiton", parent: "The Shire" }, { _id: "Foobar", isParent: true }, { _id: "Foobar Xland", parent: "Foobar" },{ _id: "Fizz" }, { _id: "The Shire", isParent: true }],
result = Object.entries(items.slice().reduce((c => (a, b) =>
    (c['val'] = b.parent || b._id, c['parent'] = b.parent, !a[c.val] ?
      a[c.val] = [b] :
      c.parent ? a[c.val].push(b) :
      a[c.val].unshift(b), a)
  )({}), ({}))).sort((a, b) =>
    a[0].localeCompare(b[0])).map(x =>
    x[1]).reduce((x, i) => x.concat(i), []);
    
console.log(result);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;