我有一个HashSet<string>
我正在加载粗俗的单词以进行过滤。问题是我的列表将包含“Fu”以及完全拼写的单词。我想要做的是过滤列表,使它只包含“Fu”,这将消除列表中任何其他形式的单词。
换句话说,我想删除列表中的所有字符串,其子字符串也是列表项。
我该怎么做呢?
我有以下excludedWords
是原始HashSet
,但它不能完全运作:
HashSet<string> copy = new HashSet<string>(exludedWords);
foreach (string w in copy)
{
foreach (string s in copy)
{
if (w.Contains(s) && w.Length > s.Length)
{
result.Remove(w);
}
}
}
答案 0 :(得分:3)
您应该将集合中的每个单词与集合中的每个单词(明显不同的)进行比较。您可以按照以下方式完成此操作(尽管我确信这不是最有效的方法,但无论如何):
string[] strings = { "a", "aa", "aaa", "b", "bb", "bbb", "c", "cc", "ccc" };
List<string> results = new List<string>(strings);
foreach (string str1 in strings) {
foreach (string str2 in strings) {
if (str1 != str2) {
if (str2.Contains(str1)) {
results.Remove(str2);
}
}
}
}
return results;
答案 1 :(得分:1)
这是一种方式......
filter.RemoveAll(a => filter.Any(b => b != a && a.Contains(b)));
其中filter是List并预先填充了过滤器字符串。
编辑: 没有看到你想要包含而不是开始。所以做了必要的mod。
答案 2 :(得分:1)
假设您只想丢弃较长的值,可以使用IEqualityComparer<string>
实现来获取新的值。
private class ShortestSubStringComparer : IComparer<string>, IEqualityComparer<string>
{
public int Compare(string x, string y)
{
if (x == null) return (y == null) ? 0 : -1;
if (y == null) return 1;
Debug.Assert(x != null && y != null);
if (this.Equals(x, y)) return x.Length.CompareTo(y.Length);
return StringComparer.CurrentCulture.Compare(x, y);
}
public bool Equals(string x, string y)
{
if (x == null) return y == null;
if (x.StartsWith(y)) return true;
if (y != null && y.StartsWith(x)) return true;
return false;
}
public int GetHashCode(string obj)
{
return obj.GetHashCode();
}
}
然后你的函数可以使用GroupBy
函数来分组并选择第一个有序的项目,如下所示:
public HashSet<string> FindShortestSubString(HashSet<string> set)
{
var comparer = new ShortestSubStringComparer();
return new HashSet<string>(set.GroupBy(e => e, comparer).Select(g => g.OrderBy(e => e, comparer).First()));
}
或者可能Min
可能会发挥作用(意味着你也不需要IComparer<string>
实现)......
public HashSet<string> FindShortestSubString(HashSet<string> set)
{
var comparer = new ShortestSubStringComparer();
return new HashSet<string>(set.GroupBy(e => e, comparer).Select(g => g.Min(e => e)));
}
答案 3 :(得分:1)
我建议不要使用这种类型的过滤。你可以节省一些cpu周期,但你会得到一些意想不到的后果,可能会让你的用户感到困惑(或者只是让他们疯狂)
例如,我们假设这是你粗俗词汇的列表......
FOO 酒吧 foohead foolery
您希望从某些内容中过滤掉所有这些字词。为了提高效率,你可以删除foohead和foolery,然后只对子字符串foo进行过滤。
你要过滤包含foo但不在你的orignal粗俗列表中的无害单词。
让我想起最近的每日WTF ......(第二次下来)
http://thedailywtf.com/Articles/Progree-of-enail-Status.aspx
答案 4 :(得分:0)
您可以使用正则表达式。这是vb,但我相信你可以转换它。
示例:
Imports System.Text.RegularExpressions
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim InputString As String
InputString = Regex.Replace(WHAT THE USER HAS ENTERED, "fu", "**")
End Sub
End Class