Группировать массив объектов javascript на основе значения в свой собственный массив объектов

1

У меня есть массив объектов Javascript, как показано ниже.

        [{

            "email": "[email protected]",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "40",
            "rate": "20",
            "amount": "200",
            "vat": "60",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "[email protected]",
            "fn": "Mike",
            "sn": "Mann",
            "phone": "01233xxxxx",
            "hours": "50",
            "rate": "70",
            "amount": "500",
            "vat": "90",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "[email protected]",
            "fn": "Fred",
            "sn": "Frogg",
            "phone": "01233xxxxx",
            "hours": "80",
            "rate": "90",
            "amount": "800",
            "vat": "100",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "[email protected]",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "90",
            "rate": "30",
            "amount": "900",
            "vat": "120",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        }]

Я в идеале хочу сгруппировать те из одного значения (email) в собственный собственный массив объектов, т.е. Если вы посмотрите на массив выше, вы увидите, что у меня есть 2 записи для одного и того же человека Алекс Макферсон. То, что я хочу сделать, - это ниже, если возможно, перемещение и объединение в вспомогательный массив и то же самое для любого другого значения, которое существует более одного раза.

    [[{

        "email": "[email protected]",
        "fn": "Alex",
        "sn": "McPherson",
        "phone": "01233xxxxx",
        "hours": "40",
        "rate": "20",
        "amount": "200",
        "vat": "60",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    },{

        "email": "[email protected]",
        "fn": "Alex",
        "sn": "McPherson",
        "phone": "01233xxxxx",
        "hours": "90",
        "rate": "30",
        "amount": "900",
        "vat": "120",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }],
    [{

        "email": "[email protected]",
        "fn": "Mike",
        "sn": "Mann",
        "phone": "01233xxxxx",
        "hours": "50",
        "rate": "70",
        "amount": "500",
        "vat": "90",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }],
    [{

        "email": "[email protected]",
        "fn": "Fred",
        "sn": "Frogg",
        "phone": "01233xxxxx",
        "hours": "80",
        "rate": "90",
        "amount": "800",
        "vat": "100",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }]]

Кажется, я не могу придумать, как использовать массив.

Теги:
object
arrays

6 ответов

2
Лучший ответ

Вы можете использовать закрытие хэш-таблицы для того же адреса электронной почты и их элементов.

var data = [{ email: "[email protected]", fn: "Alex", sn: "McPherson", phone: "01233xxxxx", hours: "40", rate: "20", amount: "200", vat: "60", agency: "test", start: "08/06/2017", end: "10/06/2017" }, { email: "[email protected]", fn: "Mike", sn: "Mann", phone: "01233xxxxx", hours: "50", rate: "70", amount: "500", vat: "90", agency: "test", start: "08/06/2017", end: "10/06/2017" }, { email: "[email protected]", fn: "Fred", sn: "Frogg", phone: "01233xxxxx", hours: "80", rate: "90", amount: "800", vat: "100", agency: "test", start: "08/06/2017", end: "10/06/2017" }, { email: "[email protected]", fn: "Alex", sn: "McPherson", phone: "01233xxxxx", hours: "90", rate: "30", amount: "900", vat: "120", agency: "test", start: "08/06/2017", end: "10/06/2017" }],
    result = data.reduce(function (hash) {
        return function (r, o) {
            if (!hash[o.email]) {
                hash[o.email] = [];
                r.push(hash[o.email]);
            }
            hash[o.email].push(o)
            return r;
        };
    }(Object.create(null)), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
  • 0
    Рад, что вы ответили, я понял, что моя попытка ответа была слишком наивной, чтобы быть хорошей: P
  • 0
    @ Нина Шольц идеальна для меня. Я думал о сокращении, но не знал, как это осуществить. Это здорово, я приму ответ :-)
1

Вы можете использовать карту ES6 для сбора данных по электронной почте, а затем извлечь полученные значения из этой карты (предполагается, что data вводятся):

Array.from(
    data.reduce( 
        (acc, o) => (acc.get(o.email).push(o), acc),
        new Map(data.map( o => [o.email, []] ))
    ), ([key, value]) => value
)

var data = [{
    "email": "[email protected]",
    "fn": "Alex",
    "sn": "McPherson",
    "phone": "01233xxxxx",
    "hours": "40",
    "rate": "20",
    "amount": "200",
    "vat": "60",
    "agency": "test",
    "start": "08/06/2017",
    "end": "10/06/2017"
}, {
    "email": "[email protected]",
    "fn": "Mike",
    "sn": "Mann",
    "phone": "01233xxxxx",
    "hours": "50",
    "rate": "70",
    "amount": "500",
    "vat": "90",
    "agency": "test",
    "start": "08/06/2017",
    "end": "10/06/2017"
}, {
    "email": "[email protected]",
    "fn": "Fred",
    "sn": "Frogg",
    "phone": "01233xxxxx",
    "hours": "80",
    "rate": "90",
    "amount": "800",
    "vat": "100",
    "agency": "test",
    "start": "08/06/2017",
    "end": "10/06/2017"
}, {
    "email": "[email protected]",
    "fn": "Alex",
    "sn": "McPherson",
    "phone": "01233xxxxx",
    "hours": "90",
    "rate": "30",
    "amount": "900",
    "vat": "120",
    "agency": "test",
    "start": "08/06/2017",
    "end": "10/06/2017"
}];

var result = Array.from(
    data.reduce( 
        (acc, o) => (acc.get(o.email).push(o), acc),
        new Map(data.map( o => [o.email, []] ))
    ), ([key, value]) => value
);

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

const groupBy = (objectList, groupingProp) => {
  // Create a dictionnary of groups.
  const dict = data.reduce((acc, entry) => {
    const groupKey = entry[groupingProp];
    acc[groupKey] = acc[groupKey] || [];
    acc[groupKey].push(entry);
    return acc;
  }, {})
  // Transform it back into a list of groups.
  return Object.values(dict);
}

// The data.
const data = [{
  "email": "[email protected]",
  "fn": "Alex",
  "sn": "McPherson",
  "phone": "01233xxxxx",
  "hours": "40",
  "rate": "20",
  "amount": "200",
  "vat": "60",
  "agency": "test",
  "start": "08/06/2017",
  "end": "10/06/2017"
},
{
  "email": "[email protected]",
  "fn": "Mike",
  "sn": "Mann",
  "phone": "01233xxxxx",
  "hours": "50",
  "rate": "70",
  "amount": "500",
  "vat": "90",
  "agency": "test",
  "start": "08/06/2017",
  "end": "10/06/2017"
},
{
  "email": "[email protected]",
  "fn": "Fred",
  "sn": "Frogg",
  "phone": "01233xxxxx",
  "hours": "80",
  "rate": "90",
  "amount": "800",
  "vat": "100",
  "agency": "test",
  "start": "08/06/2017",
  "end": "10/06/2017"
},
{
  "email": "[email protected]",
  "fn": "Alex",
  "sn": "McPherson",
  "phone": "01233xxxxx",
  "hours": "90",
  "rate": "30",
  "amount": "900",
  "vat": "120",
  "agency": "test",
  "start": "08/06/2017",
  "end": "10/06/2017"
}];

console.log(groupBy(data, 'email'));
0

Вместо внедрения DIY. Вы можете использовать ramda groupWith

Просто

R.groupWith((a ,b) => a.email === b.email, emails)
0
        let emails = [{

        "email": "[email protected]",
        "fn": "Alex",
        "sn": "McPherson",
        "phone": "01233xxxxx",
        "hours": "40",
        "rate": "20",
        "amount": "200",
        "vat": "60",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    },
    {

        "email": "[email protected]",
        "fn": "Mike",
        "sn": "Mann",
        "phone": "01233xxxxx",
        "hours": "50",
        "rate": "70",
        "amount": "500",
        "vat": "90",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    },
    {

        "email": "[email protected]",
        "fn": "Fred",
        "sn": "Frogg",
        "phone": "01233xxxxx",
        "hours": "80",
        "rate": "90",
        "amount": "800",
        "vat": "100",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    },
    {

        "email": "[email protected]",
        "fn": "Alex",
        "sn": "McPherson",
        "phone": "01233xxxxx",
        "hours": "90",
        "rate": "30",
        "amount": "900",
        "vat": "120",
        "agency": "test",
        "start": "08/06/2017",
        "end": "10/06/2017"
    }];

    let emails_obj = [];
    let output_array = [];

    emails.forEach(function(obj) {
        if (emails_obj[obj.email] == undefined) {
            emails_obj[obj.email] = []
            emails_obj[obj.email].push(obj);
        } else {
            emails_obj[obj.email].push(obj);
        }
    })        

    for (var key in emails_obj) {
        output_array.push(emails_obj[key]);
    }
    console.log(output_array);
0

Вот рабочий пример. Мы используем функцию ES6 array .reduce().

      var data = [{

            "email": "[email protected]",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "40",
            "rate": "20",
            "amount": "200",
            "vat": "60",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "[email protected]",
            "fn": "Mike",
            "sn": "Mann",
            "phone": "01233xxxxx",
            "hours": "50",
            "rate": "70",
            "amount": "500",
            "vat": "90",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "[email protected]",
            "fn": "Fred",
            "sn": "Frogg",
            "phone": "01233xxxxx",
            "hours": "80",
            "rate": "90",
            "amount": "800",
            "vat": "100",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        },
        {

            "email": "[email protected]",
            "fn": "Alex",
            "sn": "McPherson",
            "phone": "01233xxxxx",
            "hours": "90",
            "rate": "30",
            "amount": "900",
            "vat": "120",
            "agency": "test",
            "start": "08/06/2017",
            "end": "10/06/2017"
        }]
        
        
        const grouped = data.reduce((previous, current) => {
          if (!previous[current.email]) {
            const found = previous.find(element => element.email === current.email);
            if (found) {
              const index = previous.indexOf(found);
              previous.splice(index,1);
              // We add always at the top
              previous.unshift([found, current]);
            } else {
              previous.push(current);
            }
          }
          
          return previous;
        }, [])
        
        console.log(grouped);
      
.as-console-wrapper { max-height: 100% !important; top: 0; }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню