Сортировать json список чисел при наличии строки - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть форма html, которая принимает параметры, а затем приложение python (flask), которое сортирует файл json перед возвратом результатов. Это прекрасно работает, за исключением нескольких записей, где Цена не числовая, а строка (в частности, «Call for Price»).

        sortparam=request.form["inputsearch"]
        if sortparam == 'Location':
            keyparam = lambda s: s['Location']
        elif sortparam == 'Price':
            keyparam = lambda s: int(s['Price'].replace(',', ''))
        elif sortparam == 'Size':
            keyparam = lambda s: s['Size']
    with open("output/boatlist.json", "r") as jdata:
        data = json.load(jdata)
        data['boats'].sort(key=keyparam)

Вот пример json:

    "boats": [
        {
            "Name": "Lagoon 46",
            "Price": "Call For Price",
            "Size": "46 ft / 2020",
            "Location": "Vancouver, British Columbia, Canada"
        },
        {
            "Name": "Lagoon 42",
            "Price": "790,000",
            "Size": "42 ft / 2021",
            "Location": "Vancouver, British Columbia, Canada"
        },
        {
            "Name": "Leopard 40",
            "Price": "560,000",
            "Size": "40 ft / 2016",
            "Location": "Victoria, British Columbia, Canada"
        }
   ]

На данный момент я решил эту проблему, просто заменив все «Call For Pricing» на «0» при построении json, но мне было интересно, есть ли элегантный способ сортировки их до конца список.

Ответы [ 2 ]

0 голосов
/ 09 апреля 2020

Установка поля в 0 при построении JSON может быть наиболее эффективным способом, но, возможно, не самым элегантным и явным способом сделать это.

Вы можете определить функцию для использования в качестве клавиши следующим образом:

...
elif sortparam == 'Price':
    def keyparam (s):
        text = s['Price'].replace(',', '')
        try:
            return int(text)
        except ValueError as e:
            return 0
...

Или, если вы хотите придерживаться лямбда-выражений:

elif sortparam == 'Price':
    keyparams = lambda s: int(s['Price'].replace(',', '')) if s['Price'].replace(',', '').replace('-', '').isdigit() else 0

Или, если вы знаете есть только одно значение, которое не является числом:

elif sortparam == 'Price':
    keyparams = lambda s: 0 if s['Price'] == 'Call for Price' else int(s['Price'].replace(',', '')) 
0 голосов
/ 09 апреля 2020

Вы можете просто расширить функцию keyparam, добавив регистр для «Call For Price», например:

keyparam = lambda s: 0 if s['Price'].lower() == "call for price" else int(s['Price'].replace(',', ''))

Используя 0 здесь, как вы уже упоминали в своем вопросе. Однако, если вы предпочитаете, чтобы он был в конце списка, вы можете использовать float('inf') вместо:

keyparam = lambda s: float('inf') if s['Price'].lower() == "call for price" else int(s['Price'].replace(',', ''))

Сомнительно, элегантно это или нет, но это решает проблему без необходимости измените данные напрямую

Редактировать : я обновил это, чтобы использовать .lower() в строке в случае, как, например, в вашем примере, регистр строки не всегда состоит из заглавных слов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...