Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Помогите отсортировать многомерный объект! (https://javascript.ru/forum/misc/76713-pomogite-otsortirovat-mnogomernyjj-obekt.html)

AntonMs 05.02.2019 20:44

Помогите отсортировать многомерный объект!
 
Есть обьект:
var a = {
a:{"param1" : 1, "param1" : 1, "param2": 2, "param3" : 3},
b:{"param1" : 11, "param2": 22, "param3" : 33},
c:{"param1" : 111, "param2": 222, "param3" : 333}
};

Как его отсортировать по "param2" например?

P.S - Про компактное представление объектов браузерами для оптимизации - читал. Как заставить браузер не наводить "порядок" в объекте?

рони 05.02.2019 20:50

AntonMs,
:-?

AntonMs 05.02.2019 21:05

рони, ну что?

рони 05.02.2019 21:19

AntonMs,
подожду либо решения, либо изменения условий задачи.

AntonMs 05.02.2019 21:37

На данный момент задача именно такая. Вот к примеру объект, если его перебирать то сначала будет "а". А нужно что-бы b > a > c.
console.log({
b:{"param1" : 11, "param2": 22, "param3" : 33},
a:{"param1" : 1, "param1" : 1, "param2": 2, "param3" : 3},
c:{"param1" : 111, "param2": 222, "param3" : 333}
});

рони 05.02.2019 22:01

Цитата:

Сообщение от AntonMs
Вот к примеру объект

что мешает использовать массив?

AntonMs 05.02.2019 22:08

Я пришел к решению с массивом, но хочется с объектом раз он все равно создается.

рони 05.02.2019 22:13

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

AntonMs 05.02.2019 23:00

Цитата:

измените алгоритм
Стандартный алгоритм браузера представления объктов? :blink:

рони 05.02.2019 23:17

AntonMs,
console.log(
[{"param1" : 11, "param2": 22, "param3" : 33},
{"param1" : 1, "param1" : 1, "param2": 2, "param3" : 3},
{"param1" : 111, "param2": 222, "param3" : 333}
]);

это массив и массив можно отсортировать, обьекты в нормальном случае не сортируются.

можно изменить алгоритм, это значит не пытаться отсортировать обьект, поменять задачу, вместо сортировки обьекта , получить массив ключей обьекта в определённом порядке.
Цитата:

Сообщение от AntonMs
b > a > c.

почему именно b > a > c, вторая загадка для меня, но тут уже есть логика, и могут быть правила типа
Цитата:

Сообщение от AntonMs
отсортировать по "param2"


рони 05.02.2019 23:25

AntonMs,
var obj = {
b:{"param1" : 11, "param2": 22, "param3" : 33},
a:{"param1" : 1, "param2": 2, "param3" : 3},
c:{"param1" : 111, "param2": 222, "param3" : 333}
};

function fn(obj, name)
{
   return Object.keys(obj).sort((a,b)=> obj[a][name] - obj[b][name] )
}

alert(fn(obj, "param2"));

Malleys 06.02.2019 02:05

var a = {
	a: { param1: 1,   param2: 22,  param3: 3   },
	b: { param1: 11,  param2: 2,   param3: 33  },
	c: { param1: 111, param2: 222, param3: 333 }
};

// ключи оригинального объекта
alert(Object.entries(a).map(([key]) => key).join(" > "));

// создадим отсортированный объект
var aSorted = Object.entries(a)
	.sort(([, a], [, b]) => a.param2 > b.param2 ? 1 : -1)
	.reduce((m, [k, v]) => ({ ...m, [k]: v }), {})

// ключи отсортированного объекта
alert(Object.entries(aSorted).map(([key]) => key).join(" > "));


Ключи объекта не должны быть строками, которые могут быть приведены к целочисленному индексу (ecma-international.org/ecma-262/9.0/)

Цитата:

Сообщение от AntonMs
На данный момент задача именно такая. Вот к примеру объект, если его перебирать то сначала будет "а". А нужно что-бы b > a > c.

В том примере вы ничего не перебираете!

var a = {
	b: { param1: 11,  param2: 2,   param3: 33  },
	a: { param1: 1,   param2: 22,  param3: 3   },
	c: { param1: 111, param2: 222, param3: 333 }
};

for(const [key, value] of Object.entries(a)) {
	alert(key);
}

AntonMs 07.02.2019 00:07

Цитата:

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

рони 07.02.2019 00:20

Цитата:

Сообщение от AntonMs
я же пришел с другой задачей сюда...

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

AntonMs 07.02.2019 00:22

Malleys, спасибо, буду разбираться.

AntonMs 07.02.2019 00:49

рони, я понял, объекты это чисто для хранения информации, там нет учета индексов.

Malleys 07.02.2019 05:06

Цитата:

Сообщение от AntonMs
объекты это чисто для хранения информации, там нет учета индексов.

Цитата:

Сообщение от рони
браузер не обязан учитывать порядок ключей

Ключи вы можете получить при помощи метода Object.keys или Object.entries

Посмотрев определение, например, Object.entries, в спецификации (пункт 19.1.2.5), вы увидите, что для получения списка ключей/значении используется внутренний метод EnumerableOwnPropertyNames, в определении которого (пункт 7.3.21) видно, что на объекте вызывается внутренний метод [[OwnPropertyKeys]], в определении которого(9.1.11 и 9.1.11.1) видно, в каком порядке строится список ключей.

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

Затем добавляются ключи, чьи строковые представления не могут быть приведены к целочисленному значению, в порядке их создания.

Затем добавляются ключи типа Symbol, в порядке их создания.

Хотя в целом, вы не можете получить ключи в порядке создания, но договорившись, что ключи будут только строками не приводимыми к целочисленному значению(я уже это писал выше в №12), вы всё-таки получите ключи в порядке создания!

Если вам нужен только вызов внутреннего [[OwnPropertyKeys]], то используйте Reflect.ownKeys

alert(Reflect.ownKeys({ b: 1, a: 2, c: 3 }).join(" > "))

AntonMs 08.02.2019 22:14

Malleys, ваш пример работает, но к сожалению я его не понимаю, и к тому же у моего объекта цифры в именах вместо примера с "a, b, c"? И кстати я эти заклинания вообще не понимаю "m, [k, v]) => ({ ...m, [k]: v }), {}", а это "[, b]" вообще работать не должно вроде :cray: Это магия или я нуб!

Malleys 09.02.2019 12:03

Цитата:

Сообщение от AntonMs
к тому же у моего объекта цифры в именах

Если у вас ключи не представляют натуральные числа, составленные только из "0123456789", то вы можете использовать то, что описано мной выше. Также можно те цифры заменить на другие, типа "④⑥" , "❹❻", "𝟓𝟔", "𝟡𝟜", "𝟥𝟩", "𝟮𝟳" или "𝟸𝟼"

Цитата:

Сообщение от AntonMs
я эти заклинания вообще не понимаю... Это магия...

Вы можете прочитать об этом, например, в учебнике Ильи Кантора на русском языке...
https://learn.javascript.ru/destructuring
https://learn.javascript.ru/es-function
https://learn.javascript.ru/es-object

Или может всё-таки заменить объект на массив пар?
Т. е. вместо { b: {}, a: {}, c: {}} у вас будет [["b", {}], ["a", {}], ["c", {}]].

Этот массив пар вы можете передать конструктору Map. new Map([["b", {}], ["a", {}], ["c", {}]])
Перебор осуществляется в порядке вставки. Объекты типа Map гарантируют это, в отличие от объектов типа Object.

Это тоже не магия, читайте в учебнике Ильи Кантора https://learn.javascript.ru/set-map

AntonMs 09.02.2019 13:16

Цитата:

можно те цифры заменить на другие
Цитата:

Или может всё-таки заменить объект на массив пар?
Дело в том что желательно построить алгоритм так чтобы тот объект не менять. Есть объект > далее из него генерится столбчатая диаграмма по порядку, но нужно что-бы была возможность по "param2" или "param3" по выбору.

По поводу "магии" то меня сбили с толку конструкции деструктуризации, не сталкивался с ними раньше, спасибо за ссылку.

Malleys 09.02.2019 13:46

Цитата:

Сообщение от AntonMs
Дело в том что желательно построить алгоритм так чтобы тот объект не менять.

А откуда у вас появляется этот объект? В JavaScript не возможно получить ключи в порядке их создания в общем случае, вы знаете какие ключи можно получить в порядке создания, по каким-то причинам не можете то применить.

Если у вас есть возможность получить исходный код для этого объекта(он у вас есть!), то можно его разобрать при помощи acorn или esprima или *ваш любимый парсер для экспериментов*... но всё-же я рекомендую вам переделать этот объект в массив или Map

(или добавьте префикс для ключей, например "_", т. е. ключ "abc123" превратится в "_abc123", это ещё один вариант)

AntonMs 11.02.2019 00:59

Кто следит за темой подскажите ещё раз :(
var a = [
{"param1" : 1, "param1" : 1, "param2": 2, "param3" : 3},
{"param1" : 11, "param2": 22, "param3" : 33},
{"param1" : 111, "param2": 222, "param3" : 333}
];
:( 
var function_array_sort = function (array_sort, sort_param){
 return array_sort.sort(function (a, b){ return a.sort_param - b.sort_param })
};

console.log( function_array_sort(a, "сюда нужно передать 'param1'") );

Malleys 11.02.2019 03:00

var a = [
	{ param1: 1,   param2: 2,   param3: 3   },
	{ param1: 11,  param2: 22,  param3: 33  },
	{ param1: 111, param2: 222, param3: 333 }
];

function functionArraySort (arraySort, sortParam){
	return arraySort.sort(function (a, b) {
		return a[sortParam] - b[sortParam];
	});
};
	
console.log(functionArraySort(a, "param1"));

AntonMs 11.02.2019 18:39

Вот честное слово, вчера делал тоже самое!:blink:


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