PHP 怎样检测出一个字符串出现次数最多的标点符号? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
kisshere
V2EX    程序员

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

  •  
  •   kisshere 2019-07-09 14:30:30 +08:00 3326 次点击
    这是一个创建于 2287 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    直接遍历, 然后 count?

    唯一有疑问的是, 什么算"标点符号"
    kisshere
        6
    kisshere  
    OP
       2019-07-09 15:08:18 +08:00
    @Raymon111111 就是一段文本中,出现了各种中英文标点符号,在完全不知道里面存在哪些标点符号的情况下,怎样统计出现次数最多的标点符号?
    frozenway
        7
    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
        8
    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
        9
    5200  
       2019-07-09 15:20:54 +08:00
    可以先 把里面全部空格替换成空。
    然后取第一个标点符号(自己定义一个标点符号数组或者正则取也行),
    接着把匹配到的字符替换成空
    $res = str_replace(find,replace,string,count)
    替换后统计替换次数,

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

    如此遍历一遍。直到这个字符串里面没有你所谓的标点符号。
    接着取最大替换次数的 符号。
    icy37785
        10
    icy37785  
       2019-07-09 15:24:50 +08:00 via iPhone
    我也没明白难点在哪里,需要知道哪个标点符号最多,只需要知道各个标点的个数就够了,统计标点个数的方法没有十种也有八种,那么楼主到底是哪个步骤卡住了,于是来发了这么个帖子呢。
    dadababa
        11
    dadababa  
       2019-07-09 15:34:17 +08:00
    闲着没事的时候,翻一下 PHP 手册,把每个函数都看一遍,你会发现
    https://www.php.net/manual/en/function.substr-count.php
    Z1076
        12
    Z1076  
       2019-07-09 15:35:13 +08:00
    1 楼的方法不错, 也可以用正则匹配出次数再进行处理
    jowan
        13
    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
        14
    msaionyc  
       2019-07-09 15:52:17 +08:00
    猜测主要难点在于
    1.标点符号集合很大,并不是只有逗号和顿号,中英文符号,数学符号,如果全部列出来,代码会很臃肿,难看
    2.性能,朴素匹配 /split 都可以解决问题,但性能确实较差

    我的观点是:对出现频度较高的符号进行收集并放置在容器里,然后朴素匹配,或者正则挨个匹配,如果性能不行的话我确实没有想到比较好的方案
    sunny2580839896
        15
    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
        16
    Tomorrowxxy  
       2019-07-09 16:57:14 +08:00
    张嘴开喷的基本都没审题
    1 楼的方法用来获取指定符号的出现的次数是 ok 的
    楼主的问题我没有想出来好的解决办法,都是很笨的
    crysislinux
        17
    crysislinux  
       2019-07-09 16:58:36 +08:00 via Android
    遍历就好了,不要搞什么骚操作。
    azh7138m
        18
    azh7138m  
       2019-07-09 17:05:44 +08:00
    @Tomorrowxxy 张嘴开喷的基本是没审题或是没处理过多语言的问题
    什么是标点符号?
    z1154505909
        19
    z1154505909  
       2019-07-09 17:17:45 +08:00
    遍历用字符串里面出现的符号切割数组,然后看数组长度,OK
    starsriver
        20
    starsriver  
       2019-07-09 17:34:42 +08:00 via Android
    @frozenway 低效
    Tomorrowxxy
        21
    Tomorrowxxy  
       2019-07-09 17:36:48 +08:00
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2737 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 07:38 PVG 15:38 LAX 00:38 JFK 03:38
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86