我发了太多推文,页面负载很重,但请原谅我
问题
它主要由@Yametaro定期举行#来自梦美的挑战不过,这次我问了一个与PHP相关的问题。
<?php
$in = [
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
];
// 以下と同じ配列を $in から作って出力してください
//
// [
// '1st' => 'one',
// '2nd' => 'two',
// '3rd' => 'three',
// '4th' => 'four',
// '5th' => 'five',
// '6th' => 'six',
// '7th' => 'seven',
// '8th' => 'eight',
// '9th' => 'nine',
// '10th' => 'ten',
// '11th' => 'eleven',
// '12th' => 'twelve',
// '13th' => 'thirteen',
// '14th' => 'fourteen',
// '15th' => 'fifteen',
// ]
最近是史诗级的Ogiri问题,不过这次比较严重?
就算把难度提升到极致也不可能,所以我把它调整到了“即使你不是很熟悉PHP也能解决”的程度。
这是一个类似于 PHP 的问题,其中“数字索引数组”和“关联数组”在没有被区分的情况下被弄乱了。
(内部似乎是为了速度优化而分开的,但这是用户很难看到的部分)
思想点
这里要考虑的四点是:
- 如何递归或展平
- 如何确定带编号的缩写序数,例如
1st2nd3rd - 如何反转值和键
- 如何排序
我将描述我个人想要介绍的常见模式和模式。由于比较麻烦,这次就省略说明书的链接
如何递归或展平
留给array_walk_recursive
这是最 PHP 的方式。有很多答案绝大多数都使用了这个。
“我只想采用嵌套的终端键值对”
Don Pisha 会满足这个要求。但是,它不是返回一个新数组,而是设计为程序性地重写现有数组。有一个强大的部分。
<?php
$in = [
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
];
$out = [];
array_walk_recursive($in, function ($value, $key) use (&$out) {
$out[$key] = $value;
});
echo json_encode($out, JSON_PRETTY_PRINT);
/*
{
"2nd": "two",
"four": "4th",
"three": "3rd",
"one": "1st",
"10th": "ten",
"6th": "six",
"5th": "five",
"seven": "7th",
"fourteen": "14th",
"11th": "eleven",
"8th": "eight",
"thirteen": "13th",
"12th": "twelve",
"nine": "9th",
"15th": "fifteen"
}
*/
留给RecursiveArrayIteratorRecursiveIteratorIterator
该方法克服了array_walk_recursive的设计问题,可以用来返回值。使用 PHP 标准的递归迭代器函数。这个似乎也有一些用户。
... 支持 PHP 8.1 的迭代器扩展现在我可以写得很舒服了。
<?php
$in = [
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
];
// PHP 8.1 からはなんとこれでいい!
$out = [...new RecursiveIteratorIterator(new RecursiveArrayIterator($in))];
// PHP 8.0 まではこう
// - 第 2 引数に false を渡すと array_merge っぽいキー合成になる (... と同じ)
// - 第 2 引数に true を渡すと array_replace っぽいキー合成になる
// 今回は文字列キーしかないのでどちらでも同じ
//
// $out = iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator($in)), false);
echo json_encode($out, JSON_PRETTY_PRINT);
/*
{
"2nd": "two",
"four": "4th",
"three": "3rd",
"one": "1st",
"10th": "ten",
"6th": "six",
"5th": "five",
"seven": "7th",
"fourteen": "14th",
"11th": "eleven",
"8th": "eight",
"thirteen": "13th",
"12th": "twelve",
"nine": "9th",
"15th": "fifteen"
}
*/
合成使用array_filterarray_replace
这一次我没有说“确保你可以处理无限嵌套的数组”这个词。您可以使用它轻松处理最多一级的嵌套。
<?php
$in = [
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
];
$out = array_replace(array_filter($in, 'is_scalar'), ...array_filter($in, 'is_array'));
echo json_encode($out, JSON_PRETTY_PRINT);
/*
さっきまでとは少し順番が違います
{
"three": "3rd",
"10th": "ten",
"5th": "five",
"seven": "7th",
"thirteen": "13th",
"12th": "twelve",
"nine": "9th",
"2nd": "two",
"four": "4th",
"one": "1st",
"6th": "six",
"fourteen": "14th",
"11th": "eleven",
"8th": "eight",
"15th": "fifteen"
}
*/
方法是仅提取数组,将其展平一步,然后将其附加到非数组。
这实际上是我想到的第一件事。好吧,当我第一次提出这个想法时,我认为它很漂亮!但是...如果把你用的迭代器扩展方法的长度弄丢了就没位置了,我忘了是从PHP 8.1增强的?
foreach的天真循环
无需解释。它不是很酷,所以使用它的人想要艺术点在另一边(故事是什么)
如何确定编号的缩写序号,如1st 2nd 3rd
查看第一个字符是否为数字字符
我第一眼就惊呆了。在实践中,我不想过多使用它,因为存在出现未初始化字符串偏移错误的风险。
<?php
var_dump(is_numeric('1st'[0])); // true
var_dump(is_numeric('first'[0])); // false
var_dump(ctype_digit('1st'[0])); // true
var_dump(ctype_digit('first'[0])); // false
很多人用过preg_match,但这是熟悉PHP的人不用正则表达式也能搞定的部分。
转换为整数
我认为这是比较正统的。您可以在下面的说明中省略 (bool) 演员表。
<?php
var_dump((bool)(int)('1st')); // true
var_dump((bool)(int)('first')); // false
var_dump(boolval(intval('1st'))); // true
var_dump(boolval(intval('first'))); // false
var_dump((int)'1st' > 0); // true
var_dump((int)'first' > 0); // false
// var_dump('1st' > 0); // true
// var_dump('first' > 0); // ← PHP 8.0 以降と 7.4 までで動作が変わっています!要注意
string和int的模糊比较是PHP 8.0 中的重大变化请注意已输入。
使用ctype_alpha的否定
“不是所有字母”→“至少包含一个数字”
<?php
var_dump(!ctype_alpha('1st')); // true
var_dump(!ctype_alpha('first')); // false
这个方法只能用这一次。
如何反转值和键
array_walk_recursive 或 foreach if 或循环中的三元运算符
最愚蠢的方式。
<?php
$in = [
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
];
$out = [];
array_walk_recursive($in, function ($value, $key) use (&$out) {
if ((int)$value) {
$out[$value] = $key;
} else {
$out[$key] = $value;
}
});
echo json_encode($out, JSON_PRETTY_PRINT);
/*
{
"2nd": "two",
"4th": "four",
"3rd": "three",
"1st": "one",
"10th": "ten",
"6th": "six",
"5th": "five",
"7th": "seven",
"14th": "fourteen",
"11th": "eleven",
"8th": "eight",
"13th": "thirteen",
"12th": "twelve",
"9th": "nine",
"15th": "fifteen"
}
*/
如果这是一种稍微时尚的写作方式,也有类似的东西。
$out = [];
array_walk_recursive($in, function ($value, $key) use (&$out) {
(int)$value ? $out[$value] = $key : $out[$key] = $value;
});
$out = [];
array_walk_recursive($in, function ($value, $key) use (&$out) {
$out[(int)$value ? $value : $key] = (int)$value ? $key : $value;
});
$out = [];
array_walk_recursive($in, function ($value, $key) use (&$out) {
$out += (int)$value ? [$value => $key] : [$key => $value];
});
变体 1:与 min 比较 max
这是从答案中提取的。当我第一次看到它时,我感到非常惊讶。我会把它写下来,以便更容易理解。
<?php
$in = [
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
];
$out = [];
array_walk_recursive($in, function (...$pair) use (&$out) {
$out[min($pair)] = max($pair);
});
echo json_encode($out, JSON_PRETTY_PRINT);
/*
{
"2nd": "two",
"4th": "four",
"3rd": "three",
"1st": "one",
"10th": "ten",
"6th": "six",
"5th": "five",
"7th": "seven",
"14th": "fourteen",
"11th": "eleven",
"8th": "eight",
"13th": "thirteen",
"12th": "twelve",
"9th": "nine",
"15th": "fifteen"
}
*/
我懂了,数字的字符代码比字母低你正在利用它!这很聪明
我不能在生产中使用它,因为它只用于高尔夫,但我认为它非常优雅。
变体 2:sort 参数
@tadsan 先生的答案本身在本文末尾的 Ogiri 部分中进行了介绍,但还有其他巧妙之处被忽略了,因此我将在后记中介绍它们。
<?php
$in = [
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
];
$out = [];
array_walk_recursive($in, function (...$pair) use (&$out) {
sort($pair);
$out[$pair[0]] = $pair[1];
});
echo json_encode($out, JSON_PRETTY_PRINT);
/*
{
"2nd": "two",
"4th": "four",
"3rd": "three",
"1st": "one",
"10th": "ten",
"6th": "six",
"5th": "five",
"7th": "seven",
"14th": "fourteen",
"11th": "eleven",
"8th": "eight",
"13th": "thirteen",
"12th": "twelve",
"9th": "nine",
"15th": "fifteen"
}
*/
思路和minmax是一样的,不过有意思的是这里也出现了排序(虽然最后一步用到了排序)。
将array_flip 应用于展平数组
函数array_flip 将对整个条目进行反转。因此,可以只取出您想要反转的内容并在以后组合它们。
<?php
$x = [...new RecursiveIteratorIterator(new RecursiveArrayIterator([
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
]))];
// 値が 1st, 2nd, ... のものだけを取り出してキー反転
// 値が first, second, ... のものだけを取り出す
// これらを合成
$out = array_flip(array_filter($x, 'intval')) + array_filter($x, 'ctype_alpha');
echo json_encode($out, JSON_PRETTY_PRINT);
/*
{
"4th": "four",
"3rd": "three",
"1st": "one",
"7th": "seven",
"14th": "fourteen",
"13th": "thirteen",
"9th": "nine",
"2nd": "two",
"10th": "ten",
"6th": "six",
"5th": "five",
"11th": "eleven",
"8th": "eight",
"12th": "twelve",
"15th": "fifteen"
}
*/
如何排序
ksort 指定 SORT_REGULAR SORT_NATURAL
PHP 的排序函数实在是太多了,很难选择,但是ksort() 是一个按键对键值对进行排序的函数。然而,正如它是10th 及以上将出现故障。这是因为字符串的顺序是"1" "10" "2"。
<?php
$x = [...new RecursiveIteratorIterator(new RecursiveArrayIterator([
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
]))];
$out = array_flip(array_filter($x, 'intval')) + array_filter($x, 'ctype_alpha');
ksort($out);
echo json_encode($out, JSON_PRETTY_PRINT);
/*
{
"10th": "ten",
"11th": "eleven",
"12th": "twelve",
"13th": "thirteen",
"14th": "fourteen",
"15th": "fifteen",
"1st": "one",
"2nd": "two",
"3rd": "three",
"4th": "four",
"5th": "five",
"6th": "six",
"7th": "seven",
"8th": "eight",
"9th": "nine"
}
*/
SORT_NUMERIC SORT_NATURAL 通过添加任何标志,您可以更改比较方法并处理此问题。
| 旗帜 | 方法 |
|---|---|
SORT_NUMERIC |
(int) 按演员排序 |
SORT_NATURAL |
按strnatcmp的自然顺序比较排序 |
<?php
$x = [...new RecursiveIteratorIterator(new RecursiveArrayIterator([
['2nd' => 'two', 'four' => '4th'],
'three' => '3rd',
['one' => '1st'],
'10th' => 'ten',
['6th' => 'six'],
'5th' => 'five',
'seven' => '7th',
['fourteen' => '14th', '11th' => 'eleven'],
['8th' => 'eight'],
'thirteen' => '13th',
'12th' => 'twelve',
'nine' => '9th',
['15th' => 'fifteen'],
]))];
$out = array_flip(array_filter($x, 'intval')) + array_filter($x, 'ctype_alpha');
ksort($out, SORT_NUMERIC);
echo json_encode($out, JSON_PRETTY_PRINT);
ksort($out, SORT_NATURAL);
echo json_encode($out, JSON_PRETTY_PRINT);
/*
{
"1st": "one",
"2nd": "two",
"3rd": "three",
"4th": "four",
"5th": "five",
"6th": "six",
"7th": "seven",
"8th": "eight",
"9th": "nine",
"10th": "ten",
"11th": "eleven",
"12th": "twelve",
"13th": "thirteen",
"14th": "fourteen",
"15th": "fifteen"
}
*/
另一种方法是使用uksort 指定"strnatcmp" 作为回调函数。与使用SORT_NATURAL 完全相同。
uksort($out, 'strnatcmp');
答案介绍
除了模型答案,我会选择 Ogiri main。
问题作者推荐答案
$x = [...new RecursiveIteratorIterator(new RecursiveArrayIterator($in))];
$out = array_flip(array_filter($x, 'intval')) + array_filter($x, 'ctype_alpha');
ksort($out, SORT_NATURAL);
一般类别(+ 不能是 Ogiri 的类别)
愚蠢的想法也很重要。
挤成一排也没关系!
和上面一样。很高兴您注意到ctype_alpha!
array_walk_recursive 部门模型答案
+=我喜欢操作数组的人
数组连接运算符、array_merge、array_replace 的全面比较 - Qiita
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($in));
$tmp = array_fill(1, iterator_count($iterator), "");
foreach($iterator as $key => $value) {
if (preg_match("/^([0-9]+)/", $key, $match) === 1) {
$index = $match[1];
$counter = $key;
$number = $value;
} else {
preg_match("/^([0-9]+)/", $value, $match);
$index = $match[1];
$counter = $value;
$number = $key;
}
$tmp[$index] = [$counter => $number];
}
$result = array_reduce($tmp, "array_merge", []);
var_dump($result);
像这样桶排序这就是你说的
我很高兴 Dihori 第一次使用array_flip 给了我答案。
array_walk_recursive切到极限
很难看懂,不过你做的都是正常的,所以是个笼统的范畴! array_reduce这是我使用的答案的第一次观察
match我喜欢这个公式
$it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($in));
$flatNum = iterator_to_array(new \RegexIterator($it, '/^\d/'));
$flatAlpha = iterator_to_array(new \RegexIterator($it, '/^[^\d]/'));
$out = array_merge(array_flip($flatNum), $flatAlpha);
ksort($out, SORT_NATURAL);
var_dump($out);
将艺术点添加到RegexIterator
小切部
打破现代PHP! ! !
看到突如其来的strtotime,我笑了。您不必特意使用序数作为日期。
如果你问这样的问题,绝对没有人分析源代码注释并评估答案
做M?
$ys = [];
foreach ($in as $k => $xs)
if ([] < $xs)
foreach ($xs as $l => $x)
$ys[(int)[$x, $l][$l < $x]] = [[$x, $l], [$l, $x]][$l < $x];
else
$ys[(int)[$xs, $k][$k < $xs]] = [[$xs, $k], [$k, $xs]][$k < $xs];
$zs = [];
for ($i = true; $ys[$i] ?? false; $i += true)
$zs[$ys[$i][false]] = $ys[$i][true];
echo "[\n";
foreach ($zs as $k => $z) {
echo " '{$k}' => '{$z}',\n";
}
echo "]\n";
从另一边做M。太奇妙了。似乎没有单个函数调用或数字文字。除非您熟悉 PHP,否则这是一项无法完成的技术。
满足“使用$in”的条件,通过。
所有json_encode(),还有几个珀斯人。 json_decode()工匠会加分
preg_match_all('/"(\d+)\w+"/', $json = json_encode($in), $m);
$out = [];
$date = new DateTimeImmutable;
for($i = max(1, min($m[1])), $max = min(31, max($m[1])); $i <= $max; $i++) {
$key = $date->setDate(2022, 1, $i)->format('jS');
if(preg_match('/("(\w+)":)?"'.$key.'"(:"(\w+)")?/', $json, $m) && $value = $m[2] ?: $m[4]) {
$out[$key] = $value;
}
}
print_r($out);
JSON + 日期工艺的结合。太奇妙了
ob_start() + ob_get_clean(),我喜欢它,因为它像 PHP
这是var_export() 组
http_build_query()群
抱歉,我无法阅读
太忙于交换数组和可变参数
SplPriorityQueue!好久没听到你的名字了
受不了贝壳把戏的人
这也只是一个shell技巧......我想,但如果你仔细观察睡眠排序是一个实现一开始没注意,因为影响太大,无法打开进程w
PHP 无法像 JavaScript 那样实现延迟处理,除非进程打开...
特意去寻找随机数种子的人。这让我最惊讶
人们在某处忘记了$in。 @rana_kualu 的草确实是草
工作部门
表扬
赢
@akebi_mh小姐先生
我非常感谢你回答了这么多问题。 min()max()的交流让人大开眼界。
亚军(附加)
@tadsan小姐先生
由于它是通过 Sleep Sort 实现的,我将给予额外的奖励!
(很抱歉一开始没有注意到。
不错的高尔夫奖
@rana_kualu
说起高尔夫,这个人的印象。还有很多人没看问题,所以我不在乎细节(不用担心)
好算法奖
@tyabu12小姐先生
随机数调整让我不知所措。
PHP 专家奖(新增)
@nsfisis小姐先生
为高难度的装订游戏鼓掌。
我加了它是因为我再次认为难度很高!
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308626065.html