LINUX.ORG.RU

Сортировка JSON 18+

 , , , ,


0

2

Есть JSON-файл file1 с таким содержимым:

{
  "girls": {
    "0": {"name": "Маша", "position": 555},
    "1": {"name": "Анка", "position": 777},
    "2": {"name": "Ната", "position": 888}
  }
}
Подскажите как отсортировать girls по значению name и установить их position равным позиции в безымянном отсортированном списке (+1?) ?
Должно получится:
{
  "girls": {
    "0": {"name": "Анка", "position": 1},
    "1": {"name": "Маша", "position": 2},
    "2": {"name": "Ната", "position": 3}
  }
}
В man jq глядел и не понял.
Поделитесь правильными примерами на скриптовых языках, кто умеет.

Ответ на: комментарий от vvn_black

Хочу отсортировать закладки в расширении для chrome. Структура там сложнее и не я пейсал её. Так надо в общем.

superuser ★★★ ()
Последнее исправление: superuser (всего исправлений: 1)
Ответ на: комментарий от superuser

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

ЗЫ я бы лучше питоном такое решал.

filosofia ()
Ответ на: комментарий от NeXTSTEP
$ jq "[.girls[]] | sort_by(.name) | with_entries(. as $a | {key:.key | tostring, value:(.value | .position=$a.key+1)})" file1
jq: error: syntax error, unexpected '|', expecting '$' or '[' or '{' (Unix shell quoting issues?) at <top-level>, line 1:
[.girls[]] | sort_by(.name) | with_entries(. as  | {key:.key | tostring, value:(.value | .position=.key+1)})                                                 
jq: 1 compile error

А... кавычки надо одинарные.
Спасибо, работает.

superuser ★★★ ()
Последнее исправление: superuser (всего исправлений: 1)

Не нужно тебе jq, особенно, если структура еще сложнее.

var obj = {
  "girls": {
    "0": {"name": "Маша", "position": 555},
    "1": {"name": "Анка", "position": 777},
    "2": {"name": "Ната", "position": 888}
  }
}
obj.girls = Object.values(obj.girls).sort((a,b)=>a.name < b.name ? -1 : 1);
obj.girls.forEach((v,i)=>v.position = i + 1);
obj.girls = obj.girls.reduce((a, b, i) => (a[i] = b, a), {});

И получаешь свою структуру говна назад.
{
  girls: {
    '0': { name: 'Анка', position: 1 },
    '1': { name: 'Маша', position: 2 },
    '2': { name: 'Ната', position: 3 }
  }
}
Проще и понятнее, чем эти ваши заклинания на jq.

crutch_master ★★★★★ ()
Ответ на: комментарий от intelfx

ты тупо полагаешься на ключи в исходном словаре

А? Они отбрасываются же.

$ jq -c "[.girls[]]" < input.json
[{"name":"Анка","position":777},{"name":"Маша","position":555},{"name":"Ната","position":888}]

Но это же совсем не то

Ты бы сравнил для начала результат моего запроса, своего, и примера из оп-поста.

NeXTSTEP ★★ ()
Последнее исправление: NeXTSTEP (всего исправлений: 1)
Ответ на: комментарий от superuser

A на Python -е никто не напишет правильный пример?

Правильный не правильный, но рабочий однострочник:

import ujson
import pprint
from functools import reduce


data = """
{
  "girls": {
    "0": {"name": "Маша", "position": 555},
    "1": {"name": "Анка", "position": 777},
    "2": {"name": "Ната", "position": 888}
  }
}
"""


d = ujson.loads(data)
d['girls'] = reduce(
    lambda a, c: {**a, **{c[0]: {**c[1], **{'position': c[0] + 1}}}},
    enumerate(sorted(d['girls'].values(), key=lambda x: x['name'])), {})

pprint.pprint(d)
{'girls': {0: {'name': 'Анка', 'position': 1},
           1: {'name': 'Маша', 'position': 2},
           2: {'name': 'Ната', 'position': 3}}}
vvn_black ★★★★★ ()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от vvn_black

Или, если устроят ключи не текстовые и нужна только сортировка, то ещё проще:

d['girls'] = dict(enumerate(sorted(d['girls'].values(), key=lambda x: x['name'])))
vvn_black ★★★★★ ()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от ostin

ссылку на пункт стандарта js с этим заявлением в студию

превед, достаточно?

тут еще можешь почитать https://github.com/nginx/njs/issues/189

drsm ★★ ()
Последнее исправление: drsm (всего исправлений: 1)
Ответ на: комментарий от drsm

in ascending chronological order of property creation

А создавать js объект из текста в правильном для тебя порядке никто не обязан.

тут еще можешь почитать https://github.com/nginx/njs/issues/189

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

crutch_master ★★★★★ ()
Последнее исправление: crutch_master (всего исправлений: 2)
Ответ на: комментарий от crutch_master

А создавать js объект из текста в правильном для тебя порядке никто не обязан.

нет, обязан. поля у js объекта имеют упоротый, но тем не менее well defined order:

> JSON.stringify(JSON.parse('{"a":1,"b":2,"c":3,"3":4,"5":6}'))
'{"3":4,"5":6,"a":1,"b":2,"c":3}'

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

я c этим и не спорил.

другое дело, что фича эта была введена для обеспечения совместимости говнокода между браузерами, а теперь форсится как солюшен на который можно положиться, что делает interop с каким-нибудь Go довольно веселым.

drsm ★★ ()
Последнее исправление: drsm (всего исправлений: 1)
Ответ на: комментарий от drsm

нет, обязан.

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

а теперь форсится как солюшен на который можно положиться

Таким форсерам надо в стенку головой форситься.

crutch_master ★★★★★ ()
Ответ на: комментарий от superuser

Хочу отсортировать закладки в расширении для chrome. Структура там сложнее и не я пейсал её. Так надо в общем.

https://chrome.google.com/webstore/detail/speed-dial-2-new-tab/jpfpebmajhhope...

Сортировка групп по алфавиту:

$ sqlite3 ${HOME}/.config/chromium/Default/databases/chrome-extension_jpfpebmajhhopeonhlcgidhclcccjcik_0/1 "update groups set position=(select xxx from (select 1 + row_number() over (order by title) as xxx, id as idxxx from groups) where idxxx=id);"

Это в честь Релиз SQLite 3.36.0

superuser ★★★ ()
Последнее исправление: superuser (всего исправлений: 1)