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

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

27.11.2018, 18:36. Показов 4831. Ответов 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
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru