When decoding and using JSON as shown below, loop processing may be described by nesting.
nest.json
{
"a": {"A": {"A0": [1, 2], "A1": [3, 4]}, "B": {"A0": [5, 6], "A1": [7, 8]}},
"b": {"A": {"A0": [10, 20], "A1": [30, 40]}, "B": {"A0": [50, 60], "A1": [70, 80]}}
}
At this time, the value extraction of the index 1
of the key ʻA0` has the following result, but when realizing the processing with PHP or Python, there are cases where it becomes a double loop or a triple loop.
[2, 6, 20, 60]
Since a generator using yield from
is available in PHP7 and Python3.3 or later, use this function to verify whether you can break out of the nested loop.
For verification, PHP 7.1.5 and Python 3.5.0 are used.
The PHP and Python code is described as an example when it is realized by triple loop and double loop.
ʻAssuming that array_walketc. is not used, it is implemented only with
foreach`.
<?php
$nest = json_decode(file_get_contents("nest.json"), true);
/*
$nest = [
"a" => ["A" => ["A0" => [1,2], "A1" => [3,4]], "B" => ["A0" => [5,6], "A1" => [7,8]]],
"b" => ["A" => ["A0" => [10,20], "A1" => [30,40]], "B" => ["A0" => [50,60], "A1" => [70,80]]]
];
*/
$r = [];
foreach ($nest as $v1) {
foreach ($v1 as $v2) {
foreach ($v2 as $k => $v3) {
if ($k === "A0") {
$r[] = $v3[1];
}
}
}
}
print_r($r);
$r = [];
foreach ($nest as $v1) {
foreach ($v1 as $v2) {
if (isset($v2["A0"][1])) {
$r[] = $v2["A0"][1];
}
}
}
print_r($r);
Writing almost the same as PHP.
import json
from collections import OrderedDict
nest = json.load(open("nest.json"), object_pairs_hook=OrderedDict)
"""
nest = {
"a": {"A": {"A0": [1,2], "A1": [3,4]}, "B": {"A0": [5,6], "A1": [7,8]}},
"b": {"A": {"A0": [10,20], "A1": [30,40]}, "B": {"A0": [50,60], "A1": [70,80]}}
}
"""
r = []
for v1 in nest.values():
for v2 in v1.values():
for k, v3 in v2.items():
if k == "A0" and len(v3) > 1:
r.append(v3[1])
print(r)
r = []
for v1 in nest.values():
for v2 in v1.values():
if "A0" in v2 and len(v2["A0"]) > 1:
r.append(v2["A0"][1])
print(r)
yield from
Both PHP and Python can be written in the same way.
It will be relatively simple. There is no need to add loop processing even if the array hierarchy becomes deeper.
<?php
$nest = json_decode(file_get_contents("nest.json"), true);
function zslice ($n)
{
foreach($n as $k => $v) {
yield from $v;
}
}
$r = [];
foreach(zslice(zslice($nest)) as $k => $v) {
if ($k == "A0") {
$r[] = $v[1];
}
}
print_r($r);
$r = [];
foreach(zslice($nest) as $k => $v) {
if (isset($v["A0"][1])) {
$r[] = $v["A0"][1];
}
}
print_r($r);
Since it is handled by dict
, a little complicated processing is required, but basically it is the same implementation method as PHP7.
import json
from collections import OrderedDict
nest = json.load(open("nest.json"), object_pairs_hook=OrderedDict)
def zslice(n):
r = n.values() if isinstance(n, dict) else n
for v in r:
if isinstance(v, dict):
d = v.items()
elif isinstance(v, tuple) and len(v) > 1:
d = v[1].items()
else:
raise ValueError
yield from d
r = []
for k, v in zslice(zslice(nest)):
if k == "A0" and len(v) > 1:
r.append(v[1])
print(r)
r = []
for k, v in zslice(nest):
if "A0" in v and len(v["A0"]) > 1:
r.append(v["A0"][1])
print(r)
It may be simpler and easier to read by separating the zslice
as shown below.
import json
from collections import OrderedDict
nest = json.load(open("nest.json"), object_pairs_hook=OrderedDict)
def zslice1(n):
for v in n.values():
yield from v.items()
def zslice2(n):
for k, v in n:
yield from v.items()
r = []
for k, v in zslice2(zslice1(nest)):
if k == "A0" and len(v) > 1:
r.append(v[1])
print(r)
r = []
for k, v in zslice1(nest):
if "A0" in v and len(v["A0"]) > 1:
r.append(v["A0"][1])
print(r)
The output result of PHP and Python sample code described here is described.
python
Array
(
[0] => 2
[1] => 6
[2] => 20
[3] => 60
)
Array
(
[0] => 2
[1] => 6
[2] => 20
[3] => 60
)
Output result
[2, 6, 20, 60]
[2, 6, 20, 60]
If ʻobject_pairs_hook = OrderedDict is not specified in the second argument of
json.load`, the order of the elements may be different if the sample is executed several times.
pattern 1
[60, 20, 6, 2]
[60, 20, 6, 2]
Pattern 2
[6, 2, 60, 20]
[6, 2, 60, 20]
Since the order of elements is not guaranteed when creating dict
, use ʻOrderedDict` to maintain consistency.
Recommended Posts