PHP数组同键名时避免覆盖,保留多组键值对的实现方案
解决CodinGames MIME类型题目中的条目覆盖问题
这问题我之前做类似编程题时也踩过坑!核心原因是你用关联数组存储文件条目——关联数组的键是唯一的,当遇到拆分后键名相同的情况(比如a和a.wav拆分后的文件名部分都是a),后面的条目会直接覆盖前面的,自然就丢了之前的记录。
解决思路
把$files从关联数组改成索引数组,每个元素存储单个文件的完整信息(比如文件名、对应的扩展名/MIME类型),这样每个文件都是数组里的独立条目,完全不会有覆盖问题。
同时顺便优化扩展名拆分的逻辑——原代码里的正则处理多点点的场景没实现,而且用preg_split拆分单个点的方式在遇到多个点时会出错,不如用strrpos直接找最后一个点的位置,简单又可靠。
修改后的完整代码
$N = 4; // 扩展名数量 $Q = 11; // 待解析文件数 $extensions = [ "wav" => "audio/x-wav", "mp3" => "audio/mpeg", "pdf" => "application/pdf", "UNKNOW" => "UNKNOWN" ]; $files = []; // 改成索引数组,存储每个文件的独立条目 for ($i = 0; $i < $Q; $i++){ // 逐行读取输入文件名 $FNAME = stream_get_line(STDIN, 256 + 1, "\n"); // 找最后一个点的位置,处理所有带点的情况 $lastDotPos = strrpos($FNAME, '.'); if ($lastDotPos !== false && $lastDotPos < strlen($FNAME) - 1) { // 存在有效扩展名(点不在字符串最后,比如"a.wav"或"foo.bar.pdf") $ext = strtolower(substr($FNAME, $lastDotPos + 1)); // 转小写,避免大小写不匹配(比如PDF和pdf) // 匹配MIME类型 if (array_key_exists($ext, $extensions)) { $files[] = [ 'filename' => $FNAME, 'mime' => $extensions[$ext] ]; } else { $files[] = [ 'filename' => $FNAME, 'mime' => $extensions['UNKNOW'] ]; } } else { // 无扩展名,或者点在最后(比如"final."、".pdf") $files[] = [ 'filename' => $FNAME, 'mime' => $extensions['UNKNOW'] ]; } } // 按顺序输出每个文件的MIME类型 foreach ($files as $file) { echo $file['mime'] . "\n"; }
关键修改点说明
- 数组类型调整:
$files从关联数组改为索引数组,用$files[] = ...的方式追加每个文件的条目,保证所有记录都被保留。 - 扩展名拆分优化:用
strrpos找最后一个点的位置,完美处理foo.bar.pdf这种多点点的场景,拆分出的扩展名是最后一个点后的内容。 - 大小写兼容:把扩展名转成小写,避免题目中可能出现的大小写不一致问题(比如输入
A.WAV也能匹配到wav对应的MIME类型)。 - 边界情况处理:覆盖了点在开头(比如
.pdf)、点在末尾(比如final.)的场景,这些都归类为无扩展名,返回UNKNOWN。
这样修改后,你的测试用例里的a和a.wav会变成$files里的两个独立条目,输出的时候会按顺序分别返回UNKNOWN和audio/x-wav,完全符合需求。
内容的提问来源于stack exchange,提问作者John_Underscore
相关产品推荐
相关产品推荐

