我发了太多推文,页面负载很重,但请原谅我

问题

它主要由@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 的问题,其中“数字索引数组”和“关联数组”在没有被区分的情况下被弄乱了。
(内部似乎是为了速度优化而分开的,但这是用户很难看到的部分)

思想点

这里要考虑的四点是:

  • 如何递归或展平
  • 如何确定带编号的缩写序数,例如 1st 2nd 3rd
  • 如何反转值和键
  • 如何排序

我将描述我个人想要介绍的常见模式和模式。
由于比较麻烦,这次就省略说明书的链接

如何递归或展平

留给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 までで動作が変わっています!要注意

stringint的模糊比较是PHP 8.0 中的重大变化请注意已输入。

使用ctype_alpha的否定

“不是所有字母”→“至少包含一个数字”

<?php

var_dump(!ctype_alpha('1st')); // true
var_dump(!ctype_alpha('first')); // false

这个方法只能用这一次。

如何反转值和键

array_walk_recursiveforeach 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

相关文章:

  • 2022-12-23
  • 2021-08-10
  • 2022-12-23
  • 2021-12-09
  • 2021-11-14
  • 2021-11-20
  • 2022-02-15
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-16
  • 2022-12-23
  • 2022-12-23
  • 2021-12-14
相关资源
相似解决方案