如何基于前缀唯一性从现有PHP数组创建新数组
问题:保留每个前缀的首个数组元素
需求说明
遍历给定的PHP数组$booklist,仅当新数组中不存在以相同前缀(以第一个/为分隔符的前半部分)的元素时,才将当前元素加入新数组,最终保留每个前缀的首个出现元素。
原数组:
$booklist = [ 'Peppa / Season 2 / 43 The Quarrel / Page 1', 'Nursery Rhymes / Wheels On The Bus / Page 1', 'Wonderskills / Starter Book 2 / Unit 1 At The Firehouse / Part 3 / Page 3', 'Oxford Phonics World / Level 2 Short Vowels / Unit 1 Short A / Page 7', 'Peppa / Season 2 / 43 The Quarrel / Page 1', 'Nursery Rhymes / Twinkle Twinkle / Page 1', 'Wonderskills / Starter Book 2 / Unit 1 At The Firehouse / Part 2 / Page 17', 'Oxford Phonics World / Level 1 The Alphabet / Unit 8 / Review W X Y Z / Page 2', 'Peppa / Season 2 / 42 Granny And Grandpas Attic / Page 1', 'Nursery Rhymes / The Phonics Song / Page 1', 'Wonderskills / Starter Book 2 / Unit 1 At The Firehouse / Part 2 / Page 4', 'Peter Pan / Level 1 / Page 1', 'Peppa / Season 2 / 42 Granny And Grandpas Attic / Page 1', 'Nursery Rhymes / The Phonics Song / Page 1', 'Donald Duck / Page 19', 'Donald Duck / Page 18', 'Oxford Phonics World / Level 1 The Alphabet / Unit 8 / Letter Z / Page 2' ];
期望的最终数组:
$finalArray = [ 'Peppa / Season 2 / 43 The Quarrel / Page 1', 'Nursery Rhymes / Wheels On The Bus / Page 1', 'Wonderskills / Starter Book 2 / Unit 1 At The Firehouse / Part 3 / Page 3', 'Oxford Phonics World / Level 2 Short Vowels / Unit 1 Short A / Page 7', 'Peter Pan / Level 1 / Page 1', 'Donald Duck / Page 19' ];
尝试的错误代码
$finalArray = []; foreach ($booklist as $book){ foreach($finalArray as $finalItem){ $array = explode(" / ", $book); $mainBranch = $array[0]; if(0 === strpos($finalItem, $mainBranch){ /// problems in here array_push($finalArray, $book); } } }
错误分析
- 逻辑颠倒:需求是当新数组中没有相同前缀元素时添加,你写的代码却是当有匹配元素时才添加,完全反了。
- 初始循环无效:
$finalArray初始为空,第一次外层循环时内层foreach根本不会执行,导致第一个元素无法加入。 - 语法错误:
strpos的括号未闭合,会直接导致代码报错。 - 前缀匹配不严谨:仅用
strpos($finalItem, $mainBranch)可能出现部分匹配错误(比如前缀"Peppa"和"Peppa Pig"会被误判为相同)。
正确实现方法
方法一:使用辅助数组跟踪前缀(推荐,效率更高)
用一个辅助数组记录已经出现过的前缀,遍历原数组时只添加未记录过的前缀对应的元素,时间复杂度为O(n),适合大数组:
$booklist = [ // 原数组元素... ]; $finalArray = []; $seenPrefixes = []; foreach ($booklist as $book) { // 分割字符串获取第一个'/'前的前缀 $prefix = explode(' / ', $book)[0]; // 如果前缀未被记录,添加到结果数组并标记为已出现 if (!isset($seenPrefixes[$prefix])) { $finalArray[] = $book; $seenPrefixes[$prefix] = true; } } print_r($finalArray);
方法二:遍历结果数组检查前缀(效率较低)
如果一定要通过检查结果数组元素来判断,需要修正逻辑并严谨匹配前缀:
$booklist = [ // 原数组元素... ]; $finalArray = []; foreach ($booklist as $book) { $prefix = explode(' / ', $book)[0]; $prefixWithSeparator = $prefix . ' / '; // 加上分隔符避免部分匹配 $exists = false; // 遍历结果数组检查是否已有相同前缀的元素 foreach ($finalArray as $item) { if (str_starts_with($item, $prefixWithSeparator)) { $exists = true; break; } } if (!$exists) { $finalArray[] = $book; } } print_r($finalArray);
内容的提问来源于stack exchange,提问作者Liam
相关产品推荐
相关产品推荐

