简体   繁体   English

在嵌套对象数组中按属性值对对象数组进行排序

[英]Sort array of objects by property value within nested array of objects

I'm trying to figure out how to sort an array of objects by whether or not the value of a property in a nested array of objects contain the value stopped .我试图弄清楚如何通过嵌套对象数组中的属性值是否包含值stopped对对象数组进行排序。 When that value exists in any nested array of object, I need the parent object to be sorted to the top, from there, I'm trying to secondarily sort that sorted list by id .当该值存在于任何嵌套的对象数组中时,我需要将父对象排序到顶部,从那里开始,我尝试按id对该排序列表进行二次排序。

const arr = [
    {
        id: 1,
        things: [
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
        ],
    },
    {
        id: 2,
        things: [
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'stopped',
            },
        ],
    },
    {
        id: 3,
        things: [
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
        ],
    }
]

// desired result
[
    {
        id: 2,
        things: [
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'stopped',
            },
        ],
    },
    {
        id: 1,
        things: [
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
        ],
    },
    {
        id: 3,
        things: [
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
            {
                thing_id: 1, 
                status: 'started',
            },
        ],
    }
]
arr.sort((a, b) => {
    if (a.things.some(thing => thing.status === "stopped")) {
        return -1;
    } else {
        return a.id - b.id;
    }
});

You simply have to sort, checking that the current object being inspected has at least one "thing" with a status "stopped", otherwise a normal numerical order.您只需进行排序,检查当前正在检查的对象是否至少有一个状态为“已停止”的“事物”,否则为正常的数字顺序。

arr.sort((a, b) => { const stoppeds_in_a = a.things.map(obj => obj.status).filter(status => status === 'stopped').length const stoppeds_in_b = b.things.map(obj => obj.status).filter(status => status === 'stopped').length // I want that who has more 'stoppeds' occurrences first return stoppeds_in_b - stoppeds_in_a })

 const checkStopped = (things) => things.some((el) => el.status === 'stopped'); const desired = arr.sort((a, b) => checkStopped(b.things) - checkStopped(a.things));

You could introduces a helper function that partitions the collection based on a provided callback.您可以引入一个辅助函数,该函数根据提供的回调对集合进行分区。 Then concatenate them together to create the desired result.然后将它们连接在一起以创建所需的结果。

 const arr = [{id:1,things:[{thing_id:1,status:'started'},{thing_id:1,status:'started'}]},{id:2,things:[{thing_id:1,status:'started'},{thing_id:1,status:'started'},{thing_id:1,status:'stopped'}]},{id:3,things:[{thing_id:1,status:'started'},{thing_id:1,status:'started'},{thing_id:1,status:'started'},{thing_id:1,status:'started'}]}]; const [withStopped, withoutStopped] = partition(arr, item => item.things.some(item => item.status == "stopped") ); const result = withStopped.concat(withoutStopped); console.log(result); // helper function partition(iterable, fn) { const partitions = { "true": [], "false": [] }; for (const item of iterable) partitions[!!fn(item)].push(item); return [partitions[true], partitions[false]]; }

This is actually a good task for recursion.这实际上是一个很好的递归任务。 But if the structure is fixed, I took two loops and one condition.但是如果结构是固定的,我就采用了两个循环和一个条件。 If this is true I made an array push into the global res variable.如果这是真的,我将数组推送到全局 res 变量中。

 const arr = [ { id: 1, things: [ { thing_id: 1, status: 'started', }, { thing_id: 1, status: 'started', }, ], }, { id: 2, things: [ { thing_id: 1, status: 'started', }, { thing_id: 1, status: 'started', }, { thing_id: 1, status: 'stopped', }, ], }, { id: 3, things: [ { thing_id: 1, status: 'started', }, { thing_id: 1, status: 'started', }, { thing_id: 1, status: 'started', }, { thing_id: 1, status: 'started', }, ], } ] const res = []; arr.forEach(function(e) { let val = Object.values(e.things) val.forEach((t) => { if(t.status == "stopped") { res.push(e) } }) }) console.log('res', res)

you should do something like this你应该做这样的事情

const Firstresult = [];//with stopped
const SecontPartresult = [];//without stopped

arr.forEach(element => {
    element.things.forEach(thing => {
        if (thing.status == "stopped") {
            if (Firstresult.filter(x => x.id == element.id).length == 0) {
                Firstresult.push(element)
            }
        } else if (element.things.filter(x => x.status == "stopped").length === 0) {
            if (SecontPartresult.filter(x => x.id == element.id && x.things !== "stopped").length == 0) {
                SecontPartresult.push(element)
            }
        }

    });

});

SecontPartresult.forEach(element => {
    Firstresult.push(element)
});
console.table(Firstresult)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM