Форум программистов, компьютерный форум, киберфорум
JavaScript для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.52/25: Рейтинг темы: голосов - 25, средняя оценка - 4.52
1 / 1 / 0
Регистрация: 22.11.2018
Сообщений: 7

JSON создание структуры данных и вывод на экран

27.11.2018, 18:36. Показов 4771. Ответов 12
Метки json (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток! Постигаю, так сказать, Javascript.
C сервера получаю JSON вида в массив:

JSON
1
2
3
4
5
{"docId":"001", "date":"2018-03-19 12:07:07", "docName":"order1", "productName":"name1", "price":111}, 
{"docId":"001", "date":"2018-03-19 12:07:08", "docName":"order1", "productName":"name2", "price":222}, 
{"docId":"002", "date":"2018-03-19 12:07:09", "docName":"order2", "productName":"name3",  "price":333},
{"docId":"003", "date":"2018-03-20 12:07:07", "docName":"order2", "productName":"name2",  "price":444},
{"docId":"004", "date":"2018-03-21 12:07:07", "docName":"order3", "productName":"name5",  "price":555}
Необходимо создать структуру данных и вывести на экран в виде:

19 марта: всего документов: 2
№001 order1: всего товаров: 2
-name1
111
-name2
222

№002 order2: всего товаров: 1
name3
333

Т.е., необходимо сгруппировать данные по значениям, date, далее docId, потом docName.
Вот то, что я пока написал
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//функция возвращает отформатированную дату
function getFormatedDate(dateStr)
 {
var month = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'];
var date = new Date(dateStr);
    return date.getDate() + ' ' + month[date.getMonth()];
 }
 
var result = [];
 
//функция добавляет отформатированную дату в объект JSON в виде ключа
json.forEach(function(item)
{
    var d = getFormatedDate(item.date);
    
    if(result[d])
    {
    result[d].push(item);
 
    }  else {
    result[d] = [item];
     }
});
 
//Функция выводит на экран результат
Object.defineProperty(result, 'print', {
    enumerable: false,
   get: function()
    {
    var str = '';
    for(var key in this)
    {
       //key - отформатированная дата
       str += '<hr>' +key + '<br>' + 'Всего: '+ this[key].length + '<hr>';
    
        this.forEach(function(item)
      {   
        str += '№: ' + item.id + '<br>';
        str += 'doc name: ' + item.docNname + '<br>';
        str += 'date: ' + item.date + '<br>';
        str += 'name: ' + item.productName + '<br>';
        str += 'price: ' + item.price + '<br>';
      });
    }
  return str;
  }
});
 
document.write(result.print);

В итоге, данные группируются только по дате. Вопрос - как группировать по остальным ключам?
Я правильно понимаю, нужно преобразовать полученный JSON в массив с вложенными элементами, но как это сделать?
Надеюсь, я все понятно объяснил, буду благодарен за помощь или указание верного направления
1
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.11.2018, 18:36
Ответы с готовыми решениями:

Не могу понять как делать вывод на экран структуры STUDENT на заполнение и вывод данных на экран
Добрый вечер. Вот задание и мой код программы на C++ Не выходит нормально реализовать 3е задание. Первая проблема в том, что вывод на...

Создание сложной структуры данных для преобразования их в JSON
Запрашиваю из БД данные (из нескольких таблиц), соответственно количество выбранных строк из таблиц заранее не известно. в JSON нужно...

Создание, сортировка, вывод на экран файла записей (структуры) "Изделие"
Ребятки привет. Помогите пожалуйста, препод дал задание, а сама не очень понимаю Assembler)) Надо создать файл записей код изделия,...

12
Эксперт JS
6496 / 3907 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
27.11.2018, 18:56
SergeevAS, в официальной дате документа обычно компонент времени отсекается.
Получаем группировку по календарной дате и по id документа. Название документа обычно вторично по отношению к id, по названию не сортируют.
А если нужен отдельный тип документа, то у типа должно быть своё поле id типа.

Внутри документа можно например сортировать товары по наименованию productName.
1
1 / 1 / 0
Регистрация: 22.11.2018
Сообщений: 7
28.11.2018, 10:04  [ТС]
amr-now, в том-то и дело, что не знаю, как сгруппировать по двум элементам, т. е. id должен быть вложен в календарную дату
0
Эксперт JSЭксперт HTML/CSS
2151 / 1496 / 651
Регистрация: 16.04.2016
Сообщений: 3,696
28.11.2018, 21:44
SergeevAS, у Вас JSON сформирован так что прицепиться в цикле почти не за что. К примеру две разных записи, имеют одинаковые docId или docName.

Если вид, что Вам нужен, не критичен, то - https://codepen.io/qwerty_wasd/pen/mQGOOR

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
const jsonArr = [
  {"docId":"001", "date":"2018-03-19 12:07:07", "docName":"order1", "productName":"name1", "price":111}, 
  {"docId":"001", "date":"2018-03-19 12:07:08", "docName":"order1", "productName":"name2", "price":222}, 
  {"docId":"002", "date":"2018-03-19 12:07:09", "docName":"order2", "productName":"name3",  "price":333},
  {"docId":"003", "date":"2018-03-20 12:07:07", "docName":"order2", "productName":"name2",  "price":444},
  {"docId":"004", "date":"2018-03-21 12:07:07", "docName":"order3", "productName":"name5",  "price":555}
];
((d,JSONarr) => {
  class Logger {
    constructor(element, jsonArray) {
      this.pWrapper = element;
      this.jObject_op = {
        jArray: jsonArray,
        parseDate: jsonArray
        .map((e, i, a) => e.date.match(/\b.{10}\b/)[0])
        .filter((e, i, a) => a.indexOf(e) === i),
        getAObject_date: index => jsonArray
        .filter(e => e.date.includes(this.jObject_op.parseDate[index]))
      }
    }
    render() {
      this.jObject_op.parseDate.forEach((e, i, a) => {
        let logsDate = d.createElement('div'),
            headerLD = d.createElement('div');
        logsDate.className = 'logs-date';
        headerLD.className = 'header-logs-date';
        headerLD.textContent = `${new Date(e).toLocaleDateString("ru",{month: 'long', day: 'numeric'})}: всего документов: ${this.jObject_op.getAObject_date(i).length}`;
        logsDate.appendChild(headerLD);
        this.jObject_op.getAObject_date(i).forEach((el, ind, arr) => {
          let orderDate = d.createElement('div');
          orderDate.className = 'order-logs-date';
          orderDate.textContent = `№${el.docId} ${el.docName}: ${el.productName} - ${el.price}`;
          logsDate.appendChild(orderDate);
        });
        this.pWrapper.appendChild(logsDate);
      });
    }
  }
  new Logger(d.getElementById('module-log-json'), JSONarr).render();
})(document,jsonArr);
CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
*,
*:after,
*:before {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  outline: 0;
}
 
/*стили выше добавлены только для этого примера, в реальном проекте используйте normalize.css\reset.css*/
#module-log-json {
  margin: auto;
  max-width: 500px;
}
#module-log-json > .logs-date {
  margin: 10px 0;
  border: 2px solid #000000;
}
#module-log-json > .logs-date > .header-logs-date {
  font-weight: 500;
  font-size: 20px;
  text-align: center;
}
#module-log-json > .logs-date > .order-logs-date {
  margin: 10px 0;
  text-align: center;
}
HTML5
1
<div id="module-log-json"></div>
1
1 / 1 / 0
Регистрация: 22.11.2018
Сообщений: 7
29.11.2018, 10:22  [ТС]
Qwerty_Wasd, большое спасибо за ответ. На самом деле, json для примера я сильно упростил.
Суть в том, что по одному docId могут приходить разные значения docName, productName и price, поэтому необходимо реализовать и группировку по docId. В вашем примере только по дате, что я и сам сделал. Но Ваш подход интереснее)
0
Эксперт JS
6496 / 3907 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
29.11.2018, 10:33
SergeevAS, у Вас очень интересная тема для исследования механизма обработки информации в JavaScript.

Маленький уточняющий вопрос. Объясните, пожалуйста, назначение поля docName.
Чем оно отличается от docId? Это ремарка к документу? Или это название категории документов?

И где вообще хранится человеко-видимый номер документа? id может быть невидимым идентификатором из базы данных.
0
1 / 1 / 0
Регистрация: 22.11.2018
Сообщений: 7
29.11.2018, 10:51  [ТС]
amr-now, docName это название категории документов. docId и есть человеко-видимый)

Цитата Сообщение от amr-now Посмотреть сообщение
Название документа обычно вторично по отношению к id, по названию не сортируют.
Вы правы, ошибся при написании
0
Эксперт JS
6496 / 3907 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
29.11.2018, 11:30
SergeevAS, то есть в каждой категории документов своя отдельная нумерация docId?
Обычно Приказ №1 не имеет сквозную нумерацию со счет-фактурой №1.

Добавлено через 6 минут
Цитата Сообщение от SergeevAS Посмотреть сообщение
значениям, date, далее docId, потом docName.
Если в каждой категории документов своя нумерация, тогда порядок сортировки:
- календарная дата.
- категория документов,
- номер документа.

Если просто внутри даты сортируем по номеру, тогда нумерация сквозная для всех категорий товарных документов? И по категории документов не сортируем?

Добавлено через 9 минут
Цитата Сообщение от SergeevAS Посмотреть сообщение
docId могут приходить разные значения docName
Значит, у каждой категории документов отдельная нумерация.
Тогда по логике, нужно сначала сортировать по категории документа, а потом уже по номеру.

Иначе мы увидим десять документов №123, затем их разбивку по категориям.
А зачем нам нужно брать компактно десять документов с одинаковым номером?
0
1 / 1 / 0
Регистрация: 22.11.2018
Сообщений: 7
29.11.2018, 11:45  [ТС]
amr-now, порядок составления docId различается в зависимости от типа, поэтому двух документов разного типа с одинаковым docId быть не может.

Цитата Сообщение от amr-now Посмотреть сообщение
А зачем нам нужно брать компактно десять документов с одинаковым номером?
Для каждого документа нужно вывести все упомянутые в нем товары, рассчитать их количество и общую стоимость.

Но вопрос темы именно в реализации вложенной сортировки, не могу понять механизм.
0
Эксперт JS
6496 / 3907 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
29.11.2018, 12:26
SergeevAS, то есть сортировка непосредственно по наименованию категории вообще не нужна?
Правильная сортировка по категории документа уже зашита в номере документа?
0
1 / 1 / 0
Регистрация: 22.11.2018
Сообщений: 7
29.11.2018, 13:29  [ТС]
amr-now, получается, что так.
0
Эксперт JS
6496 / 3907 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
29.11.2018, 13:59
SergeevAS, на всякой случай пока оставил сортировку сначала по наименованию категории документа, потом по номеру документа. Если не надо, то легко и упростить.
PHP/HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
    <script>
        let str = `[
    {"docId":"001", "date":"2018-03-19 12:07:07", "docName":"order1", "productName":"name1", "price":111}, 
    {"docId":"001", "date":"2018-03-19 12:07:08", "docName":"order1", "productName":"name2", "price":222}, 
    {"docId":"002", "date":"2018-03-19 12:07:09", "docName":"order2", "productName":"name3",  "price":333},
    {"docId":"003", "date":"2018-03-20 12:07:07", "docName":"order2", "productName":"name2",  "price":444},
    {"docId":"004", "date":"2018-03-21 12:07:07", "docName":"order3", "productName":"name5",  "price":555}
]`;
 
        class DocHeader {
            constructor(docId, date, docName) {
                this.docId = docId; // Номер документа. Двух документов разного типа с одинаковым docId быть не может.
                this.date = date;
                this.docName = docName; // Категория документа
            }
        }
 
        class DocItem {
            constructor(docId, productName, price) {
                this.docId = docId; // Номер документа. Двух документов разного типа с одинаковым docId быть не может.
                this.productName = productName;
                this.price = price;
            }
        }
 
        // Парсим непосредственно в товарную строку, попутно создавая шапки документов.
        let docs = [],
            items = JSON.parse(str, (k, v) => {
                if (k === "") {
                    let arr = [];
                    for (let item of v) {
                        arr.push(new DocItem(item.docId, item.productName, item.price));
 
                        if (!docs.some(e => e.docId === item.docId))
                            docs.push(new DocHeader(item.docId, new Date(item.date.slice(0, 10)), item.docName));
                    }
                    v = arr;
                }
                return v;
            });
 
        let groups = groupBy(docs, e => e.date.valueOf()),
            s = "";
        for (let group of groups) {
            let docs = group.values;
            s += docs[0].date.toLocaleDateString("ru", { day: "numeric", month: "long" });
            s += `: всего документов: ${docs.length}<br />`;
 
            docs.sort((a, b) => { // https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
                if (a.docName < b.docName || (a.docName == b.docName && a.docId < b.docId))  // (a меньше b по некоторому критерию сортировки
                    return -1;
                if (a.docName > b.docName || (a.docName == b.docName && a.docId > b.docId))  // a больше b по некоторому критерию сортировки
                    return 1;
                // a должно быть равным b
                return 0;
            });
            for (let doc of docs) {
                let docItems = items.filter(e => e.docId === doc.docId).sort((a, b) =>  // https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
                    a.productName < b.productName  // (a меньше b по некоторому критерию сортировки
                        ? -1
                        : a.productName > b.productName  // a больше b по некоторому критерию сортировки
                            ? 1
                            // a должно быть равным b
                            : 0
                );
                s += `№${doc.docId} ${doc.docName}: всего товаров: ${docItems.length}<br />`;
                for (let item of docItems) {
                    s += `-${item.productName}<br />${item.price}<br />`;
                }
            }
        }
        document.write(s);
 
        /**
         * Самая простая перегрузка группирования элементов массива + опциональный компаратор:
         * Пока создает массив объектов  Ключ-Подмассив элементов, соответствующих ключу.
         * @param {Array} array Входящий массив.
         * @param {Function} keySelector Функция, возвращающая значение ключа для группы.
         * @param {Function} comparer Функция-компаратор.
         */
        function groupBy(array, keySelector, comparer) {
            let resultArray = [],
                count = array.length,
                key1, key2,
                tempArray = [];
 
            array = orderBy(array, keySelector, comparer);
 
            for (let i = 0; i < count; ++i) {
                key2 = keySelector(array[i]);
                if (key1 === key2)
                    tempArray.push(array[i]);
                else {
                    if (tempArray.length)
                        resultArray.push({ key: key1, values: tempArray });
                    key1 = key2;
                    tempArray = [array[i]];
                }
            }
            if (tempArray.length)
                resultArray.push({ key: key1, values: tempArray });
            return resultArray;
        }
 
        /**
         * Вернуть новый массив, отсортированный по возрастанию.
         * @param {Array} array Входящий массив.
         * @param {Function} keySelector Функция, возвращающая значение ключа для сортировки.
         * @param {Function} comparer Функция-компаратор.
         */
        function orderBy(array, keySelector, comparer) {
            if (!array.length) return [];
            if (comparer === undefined) {
                switch (getType(keySelector(array[0]))) {
                    case "Number":
                    case "Date":
                        comparer = (a, b) => a - b;
                        break;
                    default:
                        comparer = (a, b) => a > b ? 1 : a < b ? -1 : 0;
                        break;
                }
            }
            let resultArray = array.slice().sort((a, b) => comparer(keySelector(a), keySelector(b)));
            return resultArray;
        }
 
        /**
         * Имя типа у аргумента. Обычно с прописной буквы, кроме undefined и null.
         * Для примитивных типов подставляется имя типа-обертки.
         * @param {*} arg Произвольное значение объекта или примитивного типа, для которого нужно определить имя типа.
         */
        function getType(arg) {
            let proto, constr;
            return (arg === undefined) ? "undefined" :
                (arg === null) ? "null" :
                    (!(proto = Object.getPrototypeOf(arg)) || !(constr = proto.constructor)) ? "Object" : constr.name;
        }
    </script>
</body>
</html>
Спасибо за задачу.

Буду доделывать группировку, если ключ группировки - объект, а не примитив.
Сейчас там дата превращена в ключе в число.

Добавлено через 5 минут
Кстати, в данном варианте прямое отражение реляционных таблиц в объекты JS.
Можно сделать и второй вариант ультра-модной богатой доменной модели.
1
1 / 1 / 0
Регистрация: 22.11.2018
Сообщений: 7
29.11.2018, 15:26  [ТС]
amr-now, не ожидал, что программа так разрастется, спасибо за решение и пояснения) Буду изучать.

Цитата Сообщение от amr-now Посмотреть сообщение
Можно сделать и второй вариант ультра-модной богатой доменной модели.
Не знаю, о чем речь, но звучит интересно
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
29.11.2018, 15:26
Помогаю со студенческими работами здесь

JSON.parse: определение структуры данных
Добрый день. вопрос вот в чем. с сервера приходят данные от json_encode () вот в таком виде { &quot;id&quot; : 1, ...

Конвертация в файл формата json древовидной структуры данных
Есть класс, которые имеет следующий вид: public class Node { public string name; public List&lt;Node&gt; children; } ...

Как добиться определённой структуры данных при создании файла JSON?
Необходимо создавать json файлы с такой структурой: { &quot;pages&quot;: &quot;20&quot;, &quot;mappings&quot;: { &quot;0&quot;: &quot;value1&quot;,...

Вывод данных через ajax с типом данных JSON
Если я из обработчика пишу это, выведет, как и ежу понятно, 1 кнопку. ... $res = mysqli_query($db, 'SELECT `podmenu_name` FROM...

Вывод данных из JSON
Здравствуйте, уважаемые форумчане! Суть дела такая: нужно заполнить массив данными из файла JSON. Я уже часа четыре с этим делом е*усь,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru