使用Python

时间:2018-06-18 08:45:30

标签: php python

我需要将PHP中的小功能转换为Python。

我需要根据URI匹配JSON数据源。以下是数据的示例:

[
    {
        "group": "fruits",
        "members": [
            {
                "name": "apple",
                "id": 1
            },
            {
                "name": "orange",
                "id": 2
            }
        ]
    },
    {
        "group": "vegetables",
        "members": [
            {
                "name": "tomato",
                "id": 3
            },
            {
                "name": "carrot",
                "id": 4
            }
        ]
    },
    {
        "group": "candies",
        "members": [
            {
                "name": "chocolate",
                "id": 5
            },
            {
                "name": "cookie",
                "id": 6
            }
        ]
    }
]

变量中有一个URI,例如orange/carrot,它应返回一个匹配对象数组:

[
    {
        "name": "orange",
        "id": 2
    },
    {
        "name": "carrot",
        "id": 4
    }
]

它只能根据数据源顺序匹配它们,因此例如不接受carrot/orangetomato/cookie。需要在第一组中找到第一个URI段。如果URI显示为无效,则结果应为null。

这是我制作的PHP版本:

$uri = 'apple/carrot';
$segments = explode('/', $uri);

$groups = json_decode(file_get_contents('data/food.json'));

$matches = array_map(function (string $segment, int $index) use ($groups): ?object {
    return array_values(array_filter($groups[$index]->members, function (object $item) use ($segment): bool {
        return $item->name === $segment;
    }))[0] ?? null;
}, $segments, array_keys($segments));

$matches = in_array(null, $matches) ? null : $matches;

这就是我尝试用Python做的事情:

import os, json

uri = 'apple/carrot'
segments = uri.split('/')

dataFilePath = os.path.join(os.path.dirname(__file__), 'data/food.json')
groupsJSON = open(dataFilePath).read()
groups = json.loads(groupsJSON)

# Here I tried to work it out with map() and filter() or list comprehension

items = items if None not in items else None

我不知道什么是“Python方式”来做到这一点。你们能帮助改变这个转变吗?

2 个答案:

答案 0 :(得分:1)

这是我对" python方式"

的解释
import json
from typing import Optional

# uses python 3.6 type hints, feel free to remove
def func(uri: str, groups_json: str) -> Optional[str]:

    segments = uri.split('/')

    groups = json.loads(groups_json)

    # this a dictionary comprehension with a double for loop  
    members = {member['name']: member
               for group in groups
               for member in group['members']}

    # nb. this will throw a KeyError if segment is not valid --
    # maybe put in try / except KeyError block?
    items = [members[segment] for segment in segments]

    # make sure items are in a valid order
    if not sorted(items, key=lambda item: item['id']) == items:
        return None

    return json.dumps(items)

print(func('apple/carrot', groupsJSON))  
# --> [{"name": "apple", "id": 1}, {"name": "carrot", "id": 4}]

print(func('carrot/apple', groupsJSON))
# --> None

答案 1 :(得分:0)

我的建议是使用生成器:

def search_members(items, needles):
    local_needles = needles.split('/')
    needle = local_needles.pop(0)
    all_found = False
    for item in items:
        for member in item['members']:
            if member['name'] == needle:
              yield member
              if local_needles:
                 needle = local_needles.pop(0)
              else:
                 all_found = True
                 break
        if all_found:
            break

我无法通过这种方式找到具有更好时间共谋的场景

needles = 'orange/carrot'
result = list(search_members(items, needles))

如果提供了错误的数据,例如你可以在比较两个长度之后引发异常

if len(result) != len(needles):
   raise Exception('Wrong data supplied for url!)