Trim/Crop 双方指定文字
Trim/Crop specified text from both sides
我需要从可能很长的文本中裁剪并显示指定的关键字(周围有一些词)。
想象一下这样的文本:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua
关键字:
iscing
我的目标是在一些宽度非常有限的 TextBlock 中显示如下内容:
consectetur adipiscing elit
或(更好)
...consectetur adipiscing elit...
关键字周围的字数应基于 space 可用。
我们使用 MVVM 模式。有人对此有可行的解决方案吗?非常感谢
编辑:我现在不想突出关键字。
编辑 2:为了简单起见,假设我们只想显示第一次出现的 "iscing" 关键字。
编辑 3:再次弄清楚 - 假设您在应用程序(文档)和应用程序的其他组件(如 TextBlock)中有一些大文本显示从大文本中搜索到的关键字,周围有一些词,以便用户可以获得上下文.文本块可以在运行时调整大小,因此它应该显示更多的单词(基于大小)。关键字最好位于文本块中间的某个位置。
此函数执行您的要求:
public string Truncate(string input, string match, int nbCharMaxBefore, int nbCharMaxAfter)
{
var inputSplit = input.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
var index = 0;
while (index < inputSplit.Length)
{
if (inputSplit[index].Contains(match)) break;
index++;
}
if (index == inputSplit.Length)
{
// No match
return String.Empty;
}
// Adds all the words before the match as long as the sum of all the words is not greater than the specified limit
var previousWords = new List<string>();
var i = index - 1;
while (i >= 0)
{
var previousWord = inputSplit[i];
if (previousWord.Length + previousWords.Sum(w => w.Length) < nbCharMaxBefore)
{
previousWords.Insert(0, previousWord);
}
else
{
break;
}
i--;
}
// Adds all the words after the match as long as the sum of all the words is not greater than the specified limit
var nextWords = new List<string>();
i = index + 1;
while (i < inputSplit.Length)
{
var nextWord = inputSplit[i].TrimEnd(',');
if (nextWord.Length + nextWords.Sum(w => w.Length) < nbCharMaxAfter)
{
nextWords.Add(nextWord);
}
else
{
break;
}
i++;
}
var prev = String.Join(" ", previousWords);
var next = String.Join(" ", nextWords);
return $"...{prev} {inputSplit[index]} {next}...";
}
你可以这样使用它:
var input = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua";
var match = "iscing";
var nbCharMaxBefore = 15;
var nbCharMaxAfter = 5;
var truncatedStr = Truncate(input, match, nbCharBefore, nbCharAfter); // ...consectetur adipiscing elit...
关于 MVVM 方式,考虑到您绑定的 属性 是 MyText
,只需像这样绑定另一个 属性:
public string MyTruncatedText
{
get { return Truncate(this.MyText, this.MyMatch, this.NbCharBefore, this.NbCharAfter); }
}
最后,在 MyText
的 setter 中,您想调用 NotifyPropertyChanges(nameof(MyTruncatedProperty))
或 MVVM 工具包中的等效项。
将文本块后的数据绑定到适当的属性。
<TextBlock>
<Run x:Name="pre" Text="{Binding PrecedingText}" />
<Run x:Name="search" Text="{Binding SearchText}" FontWeight="Bold" />
<Run x:Name="succeeding" Text="{Binding SucceedingText}" />
</TextBlock>
使用以下视图模型class。
class SearchResult
{
public PrecedingText { get; set; }
public SearchText { get; set; }
public SucceedingText { get; set; }
}
我需要从可能很长的文本中裁剪并显示指定的关键字(周围有一些词)。
想象一下这样的文本:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
关键字:
iscing
我的目标是在一些宽度非常有限的 TextBlock 中显示如下内容:
consectetur adipiscing elit
或(更好)
...consectetur adipiscing elit...
关键字周围的字数应基于 space 可用。
我们使用 MVVM 模式。有人对此有可行的解决方案吗?非常感谢
编辑:我现在不想突出关键字。
编辑 2:为了简单起见,假设我们只想显示第一次出现的 "iscing" 关键字。
编辑 3:再次弄清楚 - 假设您在应用程序(文档)和应用程序的其他组件(如 TextBlock)中有一些大文本显示从大文本中搜索到的关键字,周围有一些词,以便用户可以获得上下文.文本块可以在运行时调整大小,因此它应该显示更多的单词(基于大小)。关键字最好位于文本块中间的某个位置。
此函数执行您的要求:
public string Truncate(string input, string match, int nbCharMaxBefore, int nbCharMaxAfter)
{
var inputSplit = input.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
var index = 0;
while (index < inputSplit.Length)
{
if (inputSplit[index].Contains(match)) break;
index++;
}
if (index == inputSplit.Length)
{
// No match
return String.Empty;
}
// Adds all the words before the match as long as the sum of all the words is not greater than the specified limit
var previousWords = new List<string>();
var i = index - 1;
while (i >= 0)
{
var previousWord = inputSplit[i];
if (previousWord.Length + previousWords.Sum(w => w.Length) < nbCharMaxBefore)
{
previousWords.Insert(0, previousWord);
}
else
{
break;
}
i--;
}
// Adds all the words after the match as long as the sum of all the words is not greater than the specified limit
var nextWords = new List<string>();
i = index + 1;
while (i < inputSplit.Length)
{
var nextWord = inputSplit[i].TrimEnd(',');
if (nextWord.Length + nextWords.Sum(w => w.Length) < nbCharMaxAfter)
{
nextWords.Add(nextWord);
}
else
{
break;
}
i++;
}
var prev = String.Join(" ", previousWords);
var next = String.Join(" ", nextWords);
return $"...{prev} {inputSplit[index]} {next}...";
}
你可以这样使用它:
var input = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua";
var match = "iscing";
var nbCharMaxBefore = 15;
var nbCharMaxAfter = 5;
var truncatedStr = Truncate(input, match, nbCharBefore, nbCharAfter); // ...consectetur adipiscing elit...
关于 MVVM 方式,考虑到您绑定的 属性 是 MyText
,只需像这样绑定另一个 属性:
public string MyTruncatedText
{
get { return Truncate(this.MyText, this.MyMatch, this.NbCharBefore, this.NbCharAfter); }
}
最后,在 MyText
的 setter 中,您想调用 NotifyPropertyChanges(nameof(MyTruncatedProperty))
或 MVVM 工具包中的等效项。
将文本块后的数据绑定到适当的属性。
<TextBlock>
<Run x:Name="pre" Text="{Binding PrecedingText}" />
<Run x:Name="search" Text="{Binding SearchText}" FontWeight="Bold" />
<Run x:Name="succeeding" Text="{Binding SucceedingText}" />
</TextBlock>
使用以下视图模型class。
class SearchResult
{
public PrecedingText { get; set; }
public SearchText { get; set; }
public SucceedingText { get; set; }
}