PHP 怎样检测出一个字符串出现次数最多的标点符号?

2019-07-09 14:30:30 +08:00
 kisshere

比如一个字符串:“桌子上有苹果、葡萄, 香蕉, 椰子、芒果,桃子,桔子, 西瓜, 荔枝” 上述字符串中,“英文逗号”出现次数最多,怎样将该字符串除空格外最多的标点符号检测出来?

3007 次点击
所在节点    程序员
21 条回复
sunny2580839896
2019-07-09 14:49:31 +08:00
$str = '桌子上有苹果、葡萄, 香蕉, 椰子、芒果,桃子,桔子, 西瓜, 荔枝';
$arr = explode(',',$str);
echo count($arr-1);
kisshere
2019-07-09 14:56:42 +08:00
@sunny2580839896 你理解错了,我的意思是,怎样判断一个文本中哪个标点符号出现的次数最多,而不是指定一个标点符号出现了多少次
wudanyang
2019-07-09 14:59:01 +08:00
@kisshere 楼上已经说得很明白了
Canon1014
2019-07-09 15:01:55 +08:00
@sunny2580839896 #1 哇 是个不错的思路,学到了
Raymon111111
2019-07-09 15:03:46 +08:00
没太懂难点在哪..

直接遍历, 然后 count?

唯一有疑问的是, 什么算"标点符号"
kisshere
2019-07-09 15:08:18 +08:00
@Raymon111111 就是一段文本中,出现了各种中英文标点符号,在完全不知道里面存在哪些标点符号的情况下,怎样统计出现次数最多的标点符号?
frozenway
2019-07-09 15:17:09 +08:00
```
$str = '桌子上有苹果、葡萄, 香蕉, 椰子、芒果,桃子,桔子, 西瓜, 荔枝';
$tmp = [];
for($i = 0; $i < mb_strlen($str); $i++){
$n = mb_substr($str, $i, 1);
if(trim($n) != ''){
$tmp[$n] += 1;
}
}
arsort($tmp);
print_r($tmp);
```
frozenway
2019-07-09 15:18:53 +08:00
```
Array
(
[子] => 4
[,] => 4
[、] => 2
[果] => 2
[,] => 2
[桌] => 1
[芒] => 1
[荔] => 1
[瓜] => 1
[西] => 1
[桔] => 1
[桃] => 1
[香] => 1
[椰] => 1
[蕉] => 1
[萄] => 1
[葡] => 1
[苹] => 1
[有] => 1
[上] => 1
[枝] => 1
)
```
结果去掉文字就只剩下标点符号了
5200
2019-07-09 15:20:54 +08:00
可以先 把里面全部空格替换成空。
然后取第一个标点符号(自己定义一个标点符号数组或者正则取也行),
接着把匹配到的字符替换成空
$res = str_replace(find,replace,string,count)
替换后统计替换次数,

接着再从里面取一个字符,(循环上面操作)

如此遍历一遍。直到这个字符串里面没有你所谓的标点符号。
接着取最大替换次数的 符号。
icy37785
2019-07-09 15:24:50 +08:00
我也没明白难点在哪里,需要知道哪个标点符号最多,只需要知道各个标点的个数就够了,统计标点个数的方法没有十种也有八种,那么楼主到底是哪个步骤卡住了,于是来发了这么个帖子呢。
dadababa
2019-07-09 15:34:17 +08:00
闲着没事的时候,翻一下 PHP 手册,把每个函数都看一遍,你会发现
https://www.php.net/manual/en/function.substr-count.php
Z1076
2019-07-09 15:35:13 +08:00
1 楼的方法不错, 也可以用正则匹配出次数再进行处理
jowan
2019-07-09 15:36:29 +08:00
$punctuations = ['、', ',', ',', '、', ','];
$str = '桌子上有苹果、葡萄, 香蕉, 椰子、芒果,桃子,桔子, 西瓜, 荔枝';
$arr = preg_split('/(?<!^)(?!$)/u', $str);
$arr = array_count_values($arr);
arsort($arr);
echo '<pre>';
print_r(array_intersect_key($arr, array_fill_keys($punctuations, 0)));

--------------------------
实现方式太多了?
msaionyc
2019-07-09 15:52:17 +08:00
猜测主要难点在于
1.标点符号集合很大,并不是只有逗号和顿号,中英文符号,数学符号,如果全部列出来,代码会很臃肿,难看
2.性能,朴素匹配 /split 都可以解决问题,但性能确实较差

我的观点是:对出现频度较高的符号进行收集并放置在容器里,然后朴素匹配,或者正则挨个匹配,如果性能不行的话我确实没有想到比较好的方案
sunny2580839896
2019-07-09 16:47:47 +08:00
$str = '桌子上有苹果、葡萄, 香蕉, 椰子、芒果,桃子,桔子, 西瓜, 荔枝';
$result = str_replace(' ', '', preg_replace('/[\x{4e00}-\x{9fa5}]+/u', '', $str));
$strRecord = [];
for ($i = 0; $i < mb_strlen($result, 'UTF-8'); $i++) {
$found = 0;
foreach ($strRecord as $k => $v) {
if ($result[$i] == $v['key']) {
$strRecord[$k]['count'] += 1;
$found = 1;
continue;
}
}
if (!$found) {
$strRecord[] = ['key' => $result[$i], 'count' => 1];
}
}

我好像没有了
Tomorrowxxy
2019-07-09 16:57:14 +08:00
张嘴开喷的基本都没审题
1 楼的方法用来获取指定符号的出现的次数是 ok 的
楼主的问题我没有想出来好的解决办法,都是很笨的
crysislinux
2019-07-09 16:58:36 +08:00
遍历就好了,不要搞什么骚操作。
azh7138m
2019-07-09 17:05:44 +08:00
@Tomorrowxxy 张嘴开喷的基本是没审题或是没处理过多语言的问题
什么是标点符号?
z1154505909
2019-07-09 17:17:45 +08:00
遍历用字符串里面出现的符号切割数组,然后看数组长度,OK
starsriver
2019-07-09 17:34:42 +08:00
@frozenway 低效

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/581325

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX