Как группировать из объекта массива - PullRequest
0 голосов
/ 21 апреля 2020

Я использую форму кода "Я ищу лучшие способы сделать это. У меня есть группа: данные

[
  {
     "date": "16/04/2020",
     "count": 0,
     "name": "A"
  },
  {
     "date": "16/04/2020",
     "count": 1,
     "name": "B"
  },
  {
     "date": "17/04/2020",
     "count": 0,
     "name": "B"
  }                     
  //...More.....
]
          
Ответ
{
    "date": "04/2020",
    "symtom": {
        "data": [
            {
                "date": "16/04/2020",
                "data": [
                    {
                        "name": "A",
                        "count": [
                            {
                                "date": "16/04/2020",
                                "count": 0,
                                "name": "A"
                            }
                        ]
                    },
{
                        "name": "B",
                        "count": [
                            {
                                "date": "16/04/2020",
                                "count": 1,
                                "name": "B"
                            }
                        ]
                    },
                    //...More.....
                ]
            },
            {
                "date": "17/04/2020",
                "data": [
                    {
                        "name": "B",
                        "count": [
                            {
                                "date": "17/04/2020",
                                "count": 0,
                                "name": "B"
                            }
                        ]
                    },
                    //...More.....
                ]
            }
        ]
    }
}

Можно ли исправить код и получить нужный ответ? Код:

const items = [
  {
    tab: 'Results',
    section: '2017',
    title: 'Full year Results',
    description: 'Something here',
  },
    {
    tab: 'Results',
    section: '2017',
    title: 'Half year Results',
    description: 'Something here',
  },
    {
    tab: 'Reports',
    section: 'Marketing',
    title: 'First Report',
    description: 'Something here',
  }
];

function groupAndMap(items, itemKey, childKey, predic){
    return _.map(_.groupBy(items,itemKey), (obj,key) => ({
        [itemKey]: key,
        [childKey]: (predic && predic(obj)) || obj
    }));
}

var result = groupAndMap(items,"tab","sections", 
                   arr => groupAndMap(arr,"section", "items"));


console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

ref: Групповой массив объектов, в который вложены некоторые ключи с указанными c names Но я бы хотел, чтобы строка ответа была такой (Ответ):

{
    "date": "04/2020",
    "symtom": {
        "data": [
            {
                "date": "16/04/2020",
                "data": [
                    {
                        "name": "A",
                        "count":  0,
                    },
                    {
                        "name": "B",
                        "count":  1,
                    },
                    //...More.....
                ]
            },
            {
                "date": "17/04/2020",
                "data": [
                    {
                        "name": "B",
                        "count":0,
                    },
                    //...More.....
                ]
            }
        ]
    }
}
Спасибо!

Ответы [ 3 ]

1 голос
/ 21 апреля 2020

Я бы использовал вспомогательную функцию groupBy (эта версия смоделирована после API от Ramda [заявление об отказе: я один из его авторов], но он достаточно короткий, чтобы просто включить его здесь.) Это берет функцию, которая отображает объект по значению ключа, а затем группирует ваши элементы в объект, причем эти ключи указывают на массивы вашего исходного элемента.

Нам нужно использовать это дважды, один раз, чтобы сгруппировать по месяц, а затем внутри результатов сгруппировать по дням. Остальная часть функции transform предназначена только для форматирования выходных данных так, как я думаю.

const groupBy = (fn) => (xs) => 
  xs .reduce((a, x) => ({... a, [fn(x)]: [... (a [fn (x)] || []), x]}), {})

const transform = (data) => 
  Object .entries (groupBy (({date}) => date.slice(3)) (data))     // group by month
    .map (([date, data]) => ({
      date, 
      symtom: {
        data: Object .entries (groupBy (({date}) => date) (data))  // group by day
              .map (([date, data]) => ({
                date, 
                data: data .map (({date, ...rest}) => ({...rest})) // remove date property
              }))
      }
    }))

const data = [{date: "16/04/2020", count: 0, name: "A"}, {date: "16/04/2020", count: 1, name: "B"}, {date: "17/04/2020", count: 0, name: "B"}, {date: "03/05/2020", count: 0, name: "C"}];

console .log (
  transform (data)
)
.as-console-wrapper {min-height: 100% !important; top: 0}

Если вам нужно работать в среде без Object.entries, шим достаточно легко.

1 голос
/ 21 апреля 2020

Вы можете взять функцию для каждой вложенной группы и уменьшить массив и уровни группировки.

var data = [{ date: "16/04/2020", count: 0, name: "A" }, { date: "16/04/2020", count: 1, name: "B" }, { date: "17/04/2020", count: 0, name: "B" }],
    groups = [
        (o, p) => {
            var date = o.date.slice(3),
                temp = p.find(q => q.date === date);
            if (!temp) p.push(temp = { date, symptom: { data: [] } });
            return temp.symptom.data;
        },
        ({ date }, p) => {
            var temp = p.find(q => q.date === date);
            if (!temp) p.push(temp = { date, data: [] });
            return temp.data;
        },
        ({ date, ...o }, p) => p.push(o)
    ],
    result = data.reduce((r, o) => {
        groups.reduce((p, fn) => fn(o, p), r);
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 21 апреля 2020

Я новичок, но, похоже, вы хотите, чтобы system.data.data = массив объектов с именами ключей: str и count: number, но вместо этого вы применяете весь объект к счетчику, поэтому счетчик ключей: { имя: A, количество: 0, дата: и т. д.}.

Я действительно не могу следовать вашей функции, которая разделяет данные ... но все, что вам нужно сделать, это когда счетчик отправляет объект на ссылку просто сделайте точечную нотацию, например, object.count, чтобы получить доступ к номеру и объекту таким образом, чтобы получить желаемый эффект. Надеюсь, это то, что вы спрашивали.

...