通过分组属性对对象数组进行排序

时间:2021-03-06 14:16:37

标签: javascript arrays sorting

我有以下对象数组:

更新:完整代码

export const fetchInvoices = function (firestore, currentUser) {
    const db = firestore
        .collection("customers")
        .doc(currentUser)
        .collection("subscriptions");
    let invoices = [];
    db.get().then((subscriptionSnapshot) => {
        subscriptionSnapshot.forEach((doc) => {
            doc.ref.collection("invoices").get().then((invoiceSnapshot) => {
                invoiceSnapshot.forEach(async (doc) => {
                    let invoice = {
                        "billing_reason": doc.data().billing_reason,
                        "created": doc.data().created,
                        "currency": doc.data().currency,
                        "hosted_invoice_url": doc.data().hosted_invoice_url,
                        "id": doc.id,
                        "invoice_pdf": doc.data().invoice_pdf,
                        "number": doc.data().number,
                        "period_end": doc.data().period_end,
                        "period_start": doc.data().period_start,
                        "status": doc.data().status,
                        "subtotal": doc.data().subtotal,
                        "total": doc.data().total
                    };
                    Object.defineProperty(invoice, 'invoice_id', { value: doc.id });
                    invoices.push(invoice);
                })
            })
        });
    });
    const sortedData = invoices.sort((a, b) => +(b.status === 'open') - +(a.status === 'open'));
    console.log(sortedData);
    return sortedData;
}

我想按照第一个索引上带有 status: "open" 的那些对它们进行排序,然后按照 created 进行排序。有没有办法做到这一点?

我一直在尝试使用 status: "open" 仅对 Object.values(obj).includes("open") 组进行排序以确定对象是否具有该值,然后按 truth 排序为 here。 但仍然无法做到这种“按组排序”。

3 个答案:

答案 0 :(得分:1)

按两个不同的条件排序只是将您的条件与逻辑 OR (||) 链接起来。

在第一个示例中,首先通过 data.status 将布尔值转换为整数,然后通过 data.created

const data = [ { "created": 1, "status": "draft", }, { "created": 5, "status": "paid", }, { "created": 2, "status": "open", }, { "created": 6, "status": "paid", }, { "created": 3, "status": "open", }, { "created": 4, "status": "paid", }, ];

const sortedData = data
  .sort((a, b) => +(b.status === 'open') - +(a.status === 'open') || a.created - b.created);

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

或者,由于您有多个 status 值,您可以创建一个 sortOrder 映射并在排序回调中引用它。

const data = [ { "created": 1, "status": "draft", }, { "created": 5, "status": "paid", }, { "created": 2, "status": "open", }, { "created": 6, "status": "paid", }, { "created": 3, "status": "open", }, { "created": 4, "status": "paid", }, ];

const sortOrder = {
  open: 1,
  paid: 2,
  draft: 3
}

const sortedData = data
  .sort((a, b) => sortOrder[a.status] - sortOrder[b.status] || a.created - b.created);

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

答案 1 :(得分:0)

您可以使用 filter 方法获取处于打开状态的对象,并使用 sort 方法对它们进行排序。

您可以通过在 sort 函数中相应地返回值来更改排序顺序。

const data = [
    {
        "billing_reason": "subscription_create",
        "created": 1614889156,
        "currency": "usd",
        "hosted_invoice_url": "...",
        "id": "...",
        "invoice_pdf": "...",
        "number": "82190D09-0001",
        "period_end": 1614889156,
        "period_start": 1614889156,
        "status": "draft",
        "subtotal": 3900,
        "total": 3900
    },
    {
        "billing_reason": "subscription_cycle",
        "created": 1614890009,
        "currency": "usd",
        "hosted_invoice_url": "...",
        "id": "...",
        "invoice_pdf": "...",
        "number": "82190D09-0002",
        "period_end": 1614890009,
        "period_start": 1614890009,
        "status": "paid",
        "subtotal": 3900,
        "total": 3900
    },
    {
        "billing_reason": "subscription_update",
        "created": 1614890064,
        "currency": "usd",
        "hosted_invoice_url": "...",
        "id": "...",
        "invoice_pdf": "...",
        "number": "82190D09-0003",
        "period_end": 1614890064,
        "period_start": 1614890009,
        "status": "open",
        "subtotal": -1400,
        "total": -1400
    },
    {
        "billing_reason": "subscription_create",
        "created": 1614890802,
        "currency": "usd",
        "hosted_invoice_url": "...",
        "id": "...",
        "invoice_pdf": "...",
        "number": "82190D09-0004",
        "period_end": 1614890802,
        "period_start": 1614890802,
        "status": "paid",
        "subtotal": 3900,
        "total": 3900
    },
    {
        "billing_reason": "subscription_create",
        "created": 1614892003,
        "currency": "usd",
        "hosted_invoice_url": "...",
        "id": "...",
        "invoice_pdf": "...",
        "number": "82190D09-0005",
        "period_end": 1614892002,
        "period_start": 1614892002,
        "status": "paid",
        "subtotal": 3900,
        "total": 3900
    },
    {
        "billing_reason": "subscription_create",
        "created": 1614893124,
        "currency": "usd",
        "hosted_invoice_url": "...",
        "id": "...",
        "invoice_pdf": "...",
        "number": "82190D09-0006",
        "period_end": 1614893124,
        "period_start": 1614893124,
        "status": "paid",
        "subtotal": 3900,
        "total": 3900
    },
    
]

const open = data.filter(d => d.status === "open").sort((a,b) => a.created - b.created);

console.log(open);

答案 2 :(得分:0)

如果您愿意使用一些很棒的库,这个解决方案可能适合您使用 underscore,它非常适合这种情况。

假设您将原始数组放入一个名为 data 的变量中,如 Solvenc1no's answer :

    const _ = require('underscore');
    const sortedAndGrouped = _.groupBy(_.sortBy(data, "created"),'status');
    console.log(sortedAndGrouped);

结果如下:

{ draft:
   [ { billing_reason: 'subscription_create',
       created: 1614889156,
       currency: 'usd',
       hosted_invoice_url: '...',
       id: '...',
       invoice_pdf: '...',
       number: '82190D09-0001',
       period_end: 1614889156,
       period_start: 1614889156,
       status: 'draft',
       subtotal: 3900,
       total: 3900 } ],
  paid:
   [ { billing_reason: 'subscription_cycle',
       created: 1614890009,
       currency: 'usd',
       hosted_invoice_url: '...',
       id: '...',
       invoice_pdf: '...',
       number: '82190D09-0002',
       period_end: 1614890009,
       period_start: 1614890009,
       status: 'paid',
       subtotal: 3900,
       total: 3900 },
     { billing_reason: 'subscription_create',
       created: 1614890802,
       currency: 'usd',
       hosted_invoice_url: '...',
       id: '...',
       invoice_pdf: '...',
       number: '82190D09-0004',
       period_end: 1614890802,
       period_start: 1614890802,
       status: 'paid',
       subtotal: 3900,
       total: 3900 },
     { billing_reason: 'subscription_create',
       created: 1614892003,
       currency: 'usd',
       hosted_invoice_url: '...',
       id: '...',
       invoice_pdf: '...',
       number: '82190D09-0005',
       period_end: 1614892002,
       period_start: 1614892002,
       status: 'paid',
       subtotal: 3900,
       total: 3900 },
     { billing_reason: 'subscription_create',
       created: 1614893124,
       currency: 'usd',
       hosted_invoice_url: '...',
       id: '...',
       invoice_pdf: '...',
       number: '82190D09-0006',
       period_end: 1614893124,
       period_start: 1614893124,
       status: 'paid',
       subtotal: 3900,
       total: 3900 } ],
  open:
   [ { billing_reason: 'subscription_update',
       created: 1614890064,
       currency: 'usd',
       hosted_invoice_url: '...',
       id: '...',
       invoice_pdf: '...',
       number: '82190D09-0003',
       period_end: 1614890064,
       period_start: 1614890009,
       status: 'open',
       subtotal: -1400,
       total: -1400 } ] }