我需要将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/orange
或tomato/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方式”来做到这一点。你们能帮助改变这个转变吗?
答案 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!)