【问题标题】:stri_replace_all_fixed equivalent: Replace values based on liststri_replace_all_fixed 等效项:根据列表替换值
【发布时间】:2018-05-27 22:39:03
【问题描述】:

R 有一个强大的字符串处理包stringi。特别是,我想实现与 stri_replace_all_fixed 函数相同的功能:在 Perl/PHP/Python 或 C# 中根据列表/字典替换匹配项。

#install.packages("stringi")
library(stringi)
stri_replace_all_fixed("The quick brown fox jumped over the lazy dog.",
    c("quick", "brown", "fox"), c("slow",  "black", "bear"), vectorize_all=FALSE)

输出:

“慢吞吞的黑熊跳过了懒狗。”

【问题讨论】:

  • 你的例子中的输出是什么?
  • @afc11hn 好点,我在输出中添加了更详细的 R 示例。

标签: c# python regex string perl


【解决方案1】:

使用散列来映射要替换的单词。

use warnings;
use strict;
use feature 'say';

my $string = 'The quick brown fox jumped over the lazy dog.';

my @words     = qw(quick brown fox);
my @change_to = qw(slow black bear);

my %replacement;
@replacement{@words} = @change_to;  # populate hash: quick => 'slow', ...

my $pattern = join '|', map { quotemeta } sort { length $a < length $b } @words;

$string =~ s/($pattern)/$replacement{$1}/g;

say $string;

请注意,我们需要通过lengthsort 模式的组件,以便较长的单词出现在较短的单词之前;否则,使用/no|none/'no' 可以替换为单词'none'

将其包装在具有所需接口的子例程中,比如说

sub_name($string, \@words, \@change_to);

【讨论】:

  • 太棒了,我喜欢!
  • @wp78de 太好了 :) 我添加了一个解释(按长度排序)
【解决方案2】:

一般做法是:

  1. 创建一个字典,将单词映射到它们的替换项
  2. 编译匹配字典中所有键的正则表达式
  3. 匹配正则表达式,并将每个匹配项替换为匹配键的字典值。

在 Perl 中,这样的函数如下所示:

sub replace_all {
  my ($string, %replacements) = @_;
  # Assemble the regex. 
  # Sort reverse so that longer keys are matched first.
  # Quotemeta each key in order to escape special characters.
  my $pattern = join '|', map quotemeta, reverse sort keys %replacements;
  $string =~ s/($pattern)/$replacements{$1}/g;  # replace all
  return $string;
}

测试:

use Test::More;
my $output = replace_all(
  "The quick brown fox jumped over the lazy dog.",
  quick => 'slow',
  brown => 'black',
  fox => 'bear');
my $expected = "The slow black bear jumped over the lazy dog.";
is $output, $expected;
done_testing;

【讨论】:

    【解决方案3】:

    在 Python 中,您可以将替换函数传递给 re.sub 以返回一个字符串以用作给定匹配项的替换。我们可以先创建一个包含所有模式及其替换的字典,然后编写一个查找函数来使用合适的替换字符串。

    import re
    
    
    def stri_replace_all_fixed(stri, patterns, replacements):
        pattern_to_replacement = {p: r for p, r in zip(patterns, replacements)}
    
        def switch(match):
            return pattern_to_replacement[match.group(0)]
    
        # To make sure that longer patterns are matched first
        # we sort the list by the length of its elements and reverse it
        patterns = sorted(patterns, key=len, reverse=True)
    
        print(re.sub('|'.join(patterns), switch, stri))
    
    
    pattern = "quick", "brown", "fox"
    replace = "slow", "black", "bear"
    stri_replace_all_fixed("The quick brown fox jumped over the lazy dog.", pattern, replace)
    

    【讨论】:

    • "我不确定这是否有用"——这是绝对必要的,但你拥有它的方式是错误,这种方式在 Perl 中也是错误的。需要构建模式p1|p2|...,以便最长的单词在前;否则一个简短的子词可能会被错误地替换(nothing 中的no,当nothing 发生在目标中的no 之前)。然而,在 Perl sort 默认情况下它是 按字母顺序 的,这里我们需要它的长度;看我的回答。在 Python 中,您还必须告诉它应该是 sorted 并且您想使用 key 参数。请修复它。
    • 我更新了我的答案。感谢您解释为什么这如此重要。
    猜你喜欢
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 2021-06-08
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多