Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Изменить порядок свойств объектов в большом массиве (https://javascript.ru/forum/misc/60614-izmenit-poryadok-svojjstv-obektov-v-bolshom-massive.html)

Keramet 10.01.2016 22:32

Изменить порядок свойств объектов в большом массиве
 
Есть макет таблицы на странице:
<table border="1">
    <thead>
        <tr>
            <th>Дата</th>
            <th>№ заказа</th>
            <th>ID покупателя</th>
            <th>Общая сумма</th>
            <th>Обычные продажи</th>
            <th>Рекомендованные продажи</th>
        </tr>
    </thead>

    <tbody>
    </tbody>
</table>

Есть массив объектов:
var ordersList = [
{id: 5070992, user_id: 29073781, timestamp: 1435092870, total: 1714, recommended: 0, typical: 1714 }, 
{id: 5070993, user_id: 33963628, timestamp: 1435092881, total: 10290, recommended: 0, typical: 10290 }, 
{id: 5070994, user_id: 33963648, timestamp: 1435092882, total: 2427, recommended: 0, typical: 2427 }, 
{id: 5070996, user_id: 33963559, timestamp: 1435092974, total: 1299, recommended: 0, typical: 1299 }, 
{id: 5070998, user_id: 33963814, timestamp: 1435093028, total: 2090, recommended: 0, typical: 2090 }, 
{id: 5071000, user_id: 33963819, timestamp: 1435093041, total: 16440, recommended: 0, typical: 16440 }, 
{id: 5071001, user_id: 33963837, timestamp: 1435093047, total: 5800, recommended: 0, typical: 5800 }, 
{id: 5071003, user_id: 33964044, timestamp: 1435093060, total: 5115, recommended: 0, typical: 5115 },
.....
]

массив большой: ordersList.length > 10 000

Необходимо вывести этот массив в имеющуюся таблицу. Проблема в том, что заголовок таблицы не соответствует порядку полей в объектах.
Мой вариант такой:
var tBody = document.getElementsByTagName("table")[0].getElementsByTagName("tbody")[0],
			newTr, newTd,
			i, j, N
            arrayOfObj;  // сюда планирую запихнуть свойства объектов в нужном порядке
		
		for (i = 0, N = ordersList.length; i < N; i++) {
			newTr = tBody.appendChild( document.createElement("tr") );
                        arrayOfObj = someF(ordersList[i]); // тут нужна помощь!
			for (j = 1; j <= thCount; j++) {
				newTd = newTr.appendChild( document.createElement("td") );
				newTd.textContent = arrayOfObj[j];
			}
		}

Есть ли какой-то способ определить вывод полей объекта в нужном порядке, или надо самому писать функцию (в моём варианте - это функция someF().

рони 10.01.2016 22:57

Цитата:

Сообщение от Keramet
Есть ли какой-то способ определить вывод полей объекта в нужном порядке

нет

Keramet 10.01.2016 23:02

рони,
спасибо. Краткость - сестра таланта )) Ну а как бы вы решали эту задачу (если не секрет). Хотя бы в общих чертах,если можно

Lemme 10.01.2016 23:07

Keramet, что то такое?

var ordersList = [
  {id: 5070992, user_id: 29073781, timestamp: 1435092870, total: 1714, recommended: 0, typical: 1714 },
    {id: 5070993, user_id: 33963628, timestamp: 1435092881, total: 10290, recommended: 0, typical: 10290 }
];
 
function changeOrder(ordersList, order) {
  var newOrder;

  return ordersList.map(function(item) {
    newOrder = {};
    
    for(var orderItem of order) {
      if (item.hasOwnProperty(orderItem)) {
        newOrder[orderItem] = item[orderItem];
      }
    }
    
    return newOrder;
  });
}
 
var order = ['typical', 'recommended', 'total', 'id', 'total', 'user_id', 'timestamp'],
    newOrdersList = changeOrder(ordersList, order);
     
console.log(newOrdersList[0]);
alert(JSON.stringify(newOrdersList[0]));


p.s не уверен, в том, что не говнокод :-E

Keramet 10.01.2016 23:23

Lemme,
Тоже вариант, спс. Только у меня порядок задан не
var order = ['typical', 'recommended', 'total', 'id', 'total', 'user_id', 'timestamp'],

а макетом таблицы:
<table border="1">
    <thead>
        <tr>
            <th>Дата</th>
            <th>№ заказа</th>
            <th>ID покупателя</th>
            <th>Общая сумма</th>
            <th>Обычные продажи</th>
            <th>Рекомендованные продажи</th>
        </tr>
    </thead>
    <tbody>
    </tbody>
</table>

я сделал по рабоче-крестьянски:
function inRightOrder(obj)	{
			var arr = [], ordDate = new Date (obj.timestamp * 1000);
			arr.push( ordDate.toLocaleDateString() );
			arr.push(obj.id);
			arr.push(obj.user_id);
			arr.push(obj.total.toFixed(2) + " grn");
			arr.push(obj.typical.toFixed(2) + " grn");
			arr.push(obj.recommended.toFixed(2) + " grn");
			return arr;
		}

и потом в цикле вывожу. Параллельно кое-какое форматирование сделал.

рони 10.01.2016 23:26

Создание таблицы из данных
 
Keramet,
<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
</head>

<body>
<table border="1">
    <thead>
        <tr>
            <th>Дата</th>
            <th>№ заказа</th>
            <th>ID покупателя</th>
            <th>Общая сумма</th>
            <th>Обычные продажи</th>
            <th>Рекомендованные продажи</th>
        </tr>
    </thead>

    <tbody>
    </tbody>
</table>

<script>
window.addEventListener('DOMContentLoaded', function() {
  var table = document.querySelector('table'),
  tbody = table.querySelector('tbody')
  ordersList = [
{id: 5070992, user_id: 29073781, timestamp: 1435092870, total: 1714, recommended: 0, typical: 1714 },
{id: 5070993, user_id: 33963628, timestamp: 1435092881, total: 10290, recommended: 0, typical: 10290 },
{id: 5070994, user_id: 33963648, timestamp: 1435092882, total: 2427, recommended: 0, typical: 2427 },
{id: 5070996, user_id: 33963559, timestamp: 1435092974, total: 1299, recommended: 0, typical: 1299 },
{id: 5070998, user_id: 33963814, timestamp: 1435093028, total: 2090, recommended: 0, typical: 2090 },
{id: 5071000, user_id: 33963819, timestamp: 1435093041, total: 16440, recommended: 0, typical: 16440 },
{id: 5071001, user_id: 33963837, timestamp: 1435093047, total: 5800, recommended: 0, typical: 5800 },
{id: 5071003, user_id: 33964044, timestamp: 1435093060, total: 5115, recommended: 0, typical: 5115 }],
 arr = ['timestamp', 'id', 'user_id', 'total', 'typical','recommended'],
 fix = function(a) {
    return a.toFixed(2) + " grn"
},
 obj = {'timestamp' : function(a) {
   return new Date(a*1000).toLocaleDateString()
},
'total' : fix,
'typical' : fix,
'recommended' : fix
};
ordersList.forEach(function(c, b) {
    var d = tbody.insertRow(b);
    arr.forEach(function(a, b) {
        d.insertCell(b).innerHTML = obj[a] ? obj[a](c[a]) : c[a]
    })
});

    });
</script>
</body>

</html>

Keramet 10.01.2016 23:30

Lemme,
а у меня в консоле не видно порядка - там в раскрывающимся списке все свойства по алфавиту (. Если б алертом вывести, тогда по идее будет виден порядок

Keramet 10.01.2016 23:33

рони,
:thanks:

Lemme 10.01.2016 23:33

Цитата:

Если б алертом вывести,
поправил

Цитата:

я сделал по рабоче-крестьянски:
Ох уж этот хаос, а если пару месяцев в код смотреть не будешь, потом разберешься?=)

Keramet 10.01.2016 23:54

рони,
44    ordersList.forEach(function(c, b) {
45       var d = tbody.insertRow(b);

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

Keramet 10.01.2016 23:57

Цитата:

Сообщение от Lemme (Сообщение 403227)
Ох уж этот хаос, а если пару месяцев в код смотреть не будешь, потом разберешься?=)

ну я стараюсь комментарии оставлять (что делает функция, для чего какие переменные). Ну и параллельно изучаю работы зубров JS (например, рони) :write: , чтоб корректировать свой стиль программиста

рони 11.01.2016 00:35

Цитата:

Сообщение от Keramet
поясните зачем тут b: insertRow(b)?

b индекс в какое место по порядку добавить строку (можно не указывать, если это не Google Chrome)
если ничего не добавить то Chrome считает индекс = 0 , остальные добавляют в конец строк индекс = length

Keramet 11.01.2016 00:52

рони,
понял, спасибо!

caetus 11.01.2016 04:34

если можно изменить html код и есть вариант что порядок будет меняться тогда делай так .

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	
	
<table border="1">
    <thead>
        <tr id="tab">
            <th data-info="timestamp">Дата</th>
            <th data-info="id">№ заказа</th>
            <th data-info="user_id">ID покупателя</th>
            <th data-info="total">Общая сумма</th>
            <th data-info="typical">Обычные продажи</th>
            <th data-info="recommended">Рекомендованные продажи</th>
        </tr>
    </thead>
 
    <tbody>
    </tbody>
</table>
</body>

<script>

function f (tab) {
return [].map.call(tab.children, function (elem) {
 	return elem.getAttribute('data-info') // или elem.dataset.info IE11+
 })
}

alert(f(document.getElementById('tab')))

</script>
</html>

laimas 11.01.2016 14:19

Цитата:

Сообщение от Keramet
Проблема в том, что заголовок таблицы не соответствует порядку полей в объектах.

Данные наверное из базы, значит в запросе перечислите поля в том порядке, в котором они нужны на клиенте. Если запрос возвращает большее число колонок, а клиенту нужна часть из них, то срез массива от нулевого по длину необходимую. И не надо мудрить на клиенте.

Keramet 11.01.2016 14:22

caetus,
по идее - html менять нельзя

Keramet 11.01.2016 14:23

Цитата:

Сообщение от laimas (Сообщение 403251)
Данные наверное из базы, значит в запросе перечислите поля в том порядке, в котором они нужны на клиенте. Если запрос возвращает большее число колонок, а клиенту нужна часть из них, то срез массива от нулевого по длину необходимую. И не надо мудрить на клиенте.

данные в виде файла data.js:
var ordersList = [
{id: 5070992, user_id: 29073781, timestamp: 1435092870, total: 1714, recommended: 0, typical: 1714 }, 
{id: 5070993, user_id: 33963628, timestamp: 1435092881, total: 10290, recommended: 0, typical: 10290 }, 
{id: 5070994, user_id: 33963648, timestamp: 1435092882, total: 2427, recommended: 0, typical: 2427 }, 
{id: 5070996, user_id: 33963559, timestamp: 1435092974, total: 1299, recommended: 0, typical: 1299 }, 
{id: 5070998, user_id: 33963814, timestamp: 1435093028, total: 2090, recommended: 0, typical: 2090 }, 
....
]

laimas 11.01.2016 14:28

Цитата:

Сообщение от Keramet
данные в виде файла data.js:

И он родился одновременно с рождением самого Javascript? Кто породил этот файл, если вы, скрипт ваш, то почему не в нужном порядке?

рони 11.01.2016 14:38

Цитата:

Сообщение от laimas
значит в запросе перечислите поля в том порядке, в котором они нужны на клиенте.

разве это возможно с обьектом? вроде порядок ключей в обьекте не регламентирован.

laimas 11.01.2016 14:45

Нет на сервере объектов пока я сам не сконвертирую массив в объект, это просто ключи. Да и не в этом соль, из базы ли берется, а если файл, то тем более. Файл однако получает сервер, и даже если этот файл обновляется раз в день, то выгоднее на сервере подготовить нужный порядок один раз при сохранении файла, чем при каждом запросе клиента перебирать 60 000 элементов для установления порядка. Это же просто лишняя операция.

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

Keramet 11.01.2016 15:25

laimas,
Этот файл берётся отсюда: http://javascript.ru/forum/study/602...halujjsta.html
Это просто какое-то тестовое задание, я его взял чисто в учебных целях. Пытаюсь по минимуму изменять исходные файлы, просто делаю "в лоб": не меняя исходников, не применяя никаких библиотек - только нативный JS :)

рони 11.01.2016 15:43

Цитата:

Сообщение от laimas
На сервере функций пересечения массивов хоть отбавляй, что позволяет сделать нужный порядок в любой ситуации и это плевое дело

либо вы предлагаите заменить обьект на массивы либо я вас не понимаю.

laimas 11.01.2016 15:52

В чем смысл этих заданий? Решать задачи, это ведь не только умение что-то использовать, но умение ответить себе, целесообразно ли это делать на клиенте? Ведь в реалии это будет файл с сервера, а значит выгоднее привести к порядку на нем, клиенту же только сформировать таблицу.
Может более полезную задачу решать? К примеру, есть N таблиц, данные которых нужно не только выводить, но и редактировать. А колонок у таблицы может быть много, что и неудобно для отображения, да и не обязательно нужны все при просмотре. Вот и напишите на клиенте управление: выбор необходимых для вывода колонок, выбор параметров фильтра для колонок, порядка сортировки. При этом параметры фильтра и сортировки зависят от типа данных полей базы, данные из которой и будут браться. Установки выбранные в управлении сохраняются на клиенте, а также можно сохранять пресеты.
Тут тоже придется изменять порядок свойств объекта, но это и оправдано, и пригодится.

laimas 11.01.2016 15:58

Цитата:

Сообщение от рони
либо вы предлагаите заменить обьект на массивы либо я вас не понимаю

Все зависит от того каковы исходные данные, если это JSON, то по умолчанию декодирование его и вернет объект, перестроить порядок элементов которого можно и обычным циклом. Можно при декодировании получить не объект, а обычный массив, а можно проще, перезаписывать значения объявленного массива с нужным порядком ключей (порядок их в исходном роли не играет) каждым вложением объекта сконвертированного в массив, сохраняя в текущий массив (модификация) или новый.

рони 11.01.2016 16:14

laimas,
понятно что лучше упорядочить данные на сервере, но как, я так и не понял, что вы предлагаите.

laimas 11.01.2016 16:22

Пусть исходное это объект, хотя на сервере все проще, достаточно указать true вторым параметром при декодировании json и результат будет массив. Далее каждое вложение сохранять как array_replace([a=>1, b=>1, c=>1, ...], array), где первый аргумент функции массив с нужными ключами и порядком их, второй аргумент, это каждое вложение исходного массива.
Полученный массив в json и сохранить.

Keramet 11.01.2016 16:34

Цитата:

Сообщение от laimas (Сообщение 403267)
В чем смысл этих заданий? Решать задачи, это ведь не только умение что-то использовать, но умение ответить себе, целесообразно ли это делать на клиенте? Ведь в реалии это будет файл с сервера, а значит выгоднее привести к порядку на нем, клиенту же только сформировать таблицу.

Это их из серии: "в чём смысл учить химию, физику, биологию, .... и т.д. в школе?" Ведь в реалии есть Гугл - а значит выгоднее там искать все ответы на любые вопросы.

Я это делаю для закрепления теоретических знаний и для "набития" руки, это мой подход к обучению: прочитал, осознал/разобрался, сделал!

laimas 11.01.2016 16:48

Да уж... Это из серии когда в учебных заведениях дают задания, от которых ни пользы, ни проку.
Обучение, это в первую очередь научиться размышлять. Вы хотите писать веб приложения, а это приложение из двух частей, одна на сервере, вторая у клиента, но работать они должны как единое целое. Если сервер будет отдавать клиенту неподходящие данные, то это неизбежно повлечет за собой неоправданные действия на клиенте, и наоборот, неудачный запрос клиента, слезы для сервера.
Я могу дать ссылки на темы с этого форума, где вопрошающий даже знает предмет, то есть то, что он использует в коде, но при этом совсем не понимает того, что шлет серверу совсем не потребное.
Есть и к теме "перековырять 60000 элементов на клиенте", совсем недавно, и даже наводящие вопросы не помогают, не понимает человек, что он фактически, будучи торговцем в реалии, покупал бы некий сорт помидоров не для продажи, а исключительно только для того, чтобы их тара служила подставкой для ящиков других сортов. Абсурд? Конечно. Но почему этот абсурд допустим когда решаем программную задачу?
Для того чтобы понять вкусен или нет суп, совсем не обязательно съесть всю его кастрюлю. Вы же ради уяснения "как", гоняете нехилый файл, да еще уточняя для тех кто вам отвечает - 10 000 строк.
Можно выучить наизусть все функции и конструкции языка, быть примерным кодером, не делая даже малейших ошибок в синтаксисе и прочем, но при этом так и не научиться все это использовать.

Keramet 11.01.2016 16:57

laimas,
Есть хорошее выражение: слона надо кушать по частям. для меня сейчас первостепенно изучить фронт-энд разработку. в серверной реализацией буду знакомиться позднее. не вижу ничего плохого в решении разных задач, пусть даже и не совсем практичных. Если следовать вашей логике - тогда всё можно делать на сервере и передавать в клиент "конфетку".

laimas 11.01.2016 17:06

Ну да, и чтобы понять это нужно обязательно?

Цитата:

Сообщение от Keramet
массив большой: ordersList.length > 10 000

А что тогда скупиться, да сразу 1 000 000, для усвояемости? :)

У меня же именно после этого вашего уточнения и возник вопрос - "а нахрена?"
Хотите поиметь от этого объема пользы? Ну так тогда и задача должна выглядеть иначе - как оптимизировать? Вам не приходило в голову, что обходить массив можно с двух его краев? Глядишь и польза была бы от бессмысленной задачи для клиента.

Keramet 11.01.2016 17:47

laimas,
не вижу смысла продолжать этот диспут. Всего хорошего!


Часовой пояс GMT +3, время: 02:27.