用值替换字符串中的字典键

Posted

技术标签:

【中文标题】用值替换字符串中的字典键【英文标题】:Replacing a dictionary key in a string with the value 【发布时间】:2022-01-15 20:04:18 【问题描述】:

我目前正在尝试实现一个 changeAbbreviations 函数。我正在接收来自 .csv 的消息,这些消息被加载到名为 txtContent 的文本框中。示例消息如下所示:

“嘿,刚刚听到你的语音邮件,我是 ROFL,谢谢你的笑话”

我有一个字典,其中包含一个 textspeak 缩写列表及其延长值,我还从一个 .csv 中读取,其结构如下:

ROFL,笑着在地上打滚 大声笑,大声笑 AFK,远离键盘 BRB,马上回来 等等

我要实现的是,在按钮单击事件上,该函数将被调用,用拉长的值替换缩写并将新消息推送到名为 txtContentClean 的文本框

该函数将遍历字符串中的每个单词,如果单词与字典键之一匹配,它将用值替换它。

我不太确定如何进行,并希望有人能够向我展示如何正确实现这一点。到目前为止,我已经在下面复制了我的代码:

字典:

    public partial class MainWindow : Window
    
        public MainWindow()
        
            InitializeComponent();
        

         Dictionary<string, string> dictionary = File.ReadAllLines("textwords.csv").Select(x => 
         x.Split(",", StringSplitOptions.RemoveEmptyEntries))
        .ToDictionary(key => key.FirstOrDefault().Trim(),
        value => value.Skip(1).FirstOrDefault().Trim());

更改缩写功能:

       public void changeAbbreviations(string content, Dictionary<string, string> dictionary)
        

            var abbreviations = new List<string>();
            foreach (string word in content.Split(' '))
            
                bool wordExists = dictionary.ContainsKey(word);
                if (wordExists)
                
                    abbreviations.Add(word);
                
            

            foreach (string word in abbreviations)
            
                content.Replace(word, dictionary[word]);
            

            txtContentClean.Text = content;
        

按钮事件:

        private void btnFilter_Click(object sender, RoutedEventArgs e)
        
            changeAbbreviations();
        

我希望我已经正确设置了这个问题,并感谢您的任何帮助:)

【问题讨论】:

您也必须发布 textwords.csv 的一部分,以便我们进行测试 你还需要content = content.Replace(word, dictionary[word];,因为Replace不修改原始字符串,它返回修改后的字符串。如果有很多替换项,我建议使用 StringBuilder 代替 content 作为字符串 是否需要考虑大小写变化,比如“rofl”? 【参考方案1】:

我建议使用正则表达式并匹配而不是Split,这可以在我们有标点符号时帮助我们,例如

Call me ASAP!

正则表达式可以很好地提取"ASAP",我们可以从字典中将其替换为as soon as possible;当Split 将返回"Call", "me", "ASAP!" 而我们遇到麻烦"ASAP!"

代码:

 using System.Text.RegularExpressions;

 ...

 //DONE: 
 //  1. ReadLines - we don't want premature materialization
 //  2. Split(..2..) - no more then 2 items (in case text has commas)
 private m_Dictionary = File
   .ReadLines("textwords.csv")
   .Select(x => x.Split(",", 2, StringSplitOptions.RemoveEmptyEntries | ))
   .Where(pair => pair.Length == 2)
   .ToDictionary(pair => pair[0], pair => pair[1]);

 //DONE: business logic only, no UI 
 public string changeAbbreviations(string content, 
                                   IDictionary<string, string> dictionary = null) 
   dictionary = dictionary ?? m_Dictionary;       

   if (string.IsNullOrEmpty(content))
     return content;

   // We try to change all uppercase words like ASAP, LOL etc. 
   return Regex.Replace(content, @"\b\pLu+\b", match => 
     dictionary.TryGetValue(match.Value, out var text) 
       ? text 
       : match.Value);
 

 // UI only
 private void btnFilter_Click(object sender, RoutedEventArgs e) 
   txtContentClean.Text = changeAbbreviations(txtContentClean.Text);
 

编辑:如果我们允许 digits 包含在缩写中,例如 "P2P", "I18N""M8",则模式可以是

 \b(?:\pLu+[0-9]*)+\b

 ...

 return Regex.Replace(content, @"\b(?:\pLu+[0-9]*)+\b", match => 
   dictionary.TryGetValue(match.Value, out var text) 
     ? text 
     : match.Value);

 ... 

【讨论】:

如果我想修改它以包含 L8R、Later 或 M8 等缩写词,Mate 是否需要对正则表达式进行大量调整? @Paddington:如果缩写必须字母开始并且可以包含数字(例如P2PI18NK8SM8) 正则表达式可以是(\pLu+[0-9]*)+\b(\pLu+[0-9]*)+\b,如果缩写应该是一个单词 啊,我明白了,我还在掌握正则表达式语法 tysm!【参考方案2】:

试试这个

string content="LOL you are funny";
content =  ChangeAbbreviations(content,dictionary);

结果

Laughing out loud you are funny

代码

public string ChangeAbbreviations(string content, Dictionary<string, string> dictionary)

    string pattern =@"[^0-9a-zA-Z:,]+";
    string[] strArray = Regex.Split(content, pattern,
                                  RegexOptions.IgnoreCase,
                                  TimeSpan.FromMilliseconds(500));

    for (var i=0; i < strArray.Length; i++)
      if ( dictionary.TryGetValue(strArray[i], out var wordFull)) 
                strArray[i] =  wordFull;
    
     return string.Join(" ", strArray);

【讨论】:

以上是关于用值替换字符串中的字典键的主要内容,如果未能解决你的问题,请参考以下文章

Python递归替换嵌套字典键中的字符?

Python - 从键替换特殊字符,字典中的值

使用字典替换 Pandas 列中字符串中的字符串

用值替换列表中的元素,以新列表结尾

用字典值替换 Pandas Dataframe 中的部分字符串

用值替换空的 UITextfield