【问题标题】: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”?

标签: c# wpf dictionary


【解决方案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\p{Lu}+\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(?:\p{Lu}+[0-9]*)+\b

即

 ...

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

 ... 

【讨论】:

  • 如果我想修改它以包含 L8R、Later 或 M8 等缩写词,Mate 是否需要对正则表达式进行大量调整?
  • @Paddington:如果缩写必须从字母开始并且可以包含数字(例如P2P、I18N、K8S、M8) 正则表达式可以是(\p{Lu}+[0-9]*)+ 或\b(\p{Lu}+[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);
}

【讨论】:

    猜你喜欢
    • 2018-09-11
    • 2017-07-15
    • 2017-08-24
    • 2021-01-02
    • 1970-01-01
    • 2020-08-04
    • 2020-09-22
    • 1970-01-01
    • 2019-10-01
    相关资源
    最近更新 更多