假设我有以下2个数组。。。
string[] A = ["word1", "word2", "word3"];
string[] B = ["word0", "word1", "word2", "word3", "word4", "word5", "word6", "word1", "word2", "word3"];
如果我想将A与B进行比较,并删除B中的第一个出现,那么它看起来是这样的。。。
string[] B = ["word0", " ", " ", " ", "word4", "word5", "word6", "word1", "word2", "word3"];
我该怎么做?
一个简单的方法是使用Array.IndexOf
在B
:中查找来自A
的每个单词的第一个出现
foreach (var word in A)
{
var index = Array.IndexOf(B, word);
if (index >= 0) {
B[index] = " "; // or whatever other value
}
}
请注意,如果替换值本身存在于A
中,则这可能无法按预期工作——如果可能的话,您应该指定希望发生的情况。
更新:看起来您想在B
中查找并替换子序列A
作为一个整体,而不是单个元素。这是一个非常不同的问题。一个(幼稚的)实现是:
var start = Enumerable.Range(0, B.Length - A.Length + 1)
.Where(i => B.Skip(i).Take(A.Length).SequenceEqual(A))
.DefaultIfEmpty(-1)
.First();
if (start != -1)
{
for (var i = 0; i < A.Length; ++i)
{
B[start + i] = " ";
}
}
我完全支持@Jon给出的答案。它相当快速、简洁和精确。尽管如此,我还是有一个完全不同的方法,一个更实用的方法,以防万一到了string[]
,你实际上想说一些更流畅的东西:
假设你有一个可能无限的字符串序列,而不是B的原始数组。它可以是任何东西:直接从数据库中读取实体,一个一元字符串生成器,任何东西:
string[] A = ["word1", "word2", "word3"];
IEnumerable[] B = ...;
你可以给自己写一个很好的小扩展方法:
public static class MyHelpers {
public static IEnumerable<string> ReplaceFirstOccurrencesWithEmpty(this IEnumerable<string> @this, IEnumerable<string> a) {
// prepare a HashSet<string> to know how many A elements there still exist
var set = new Hashset<string>(a);
// iterate and apply the rule you asked about
// virtually forever (if needed)
foreach (var value in @this) {
if (set.Remove(value))
yield return "";
else
yield return value;
}
}
}
然后你可以这样使用它,即使是在你最初的A和B阵列上:
string[] A = ["word1", "word2", "word3"];
string[] B = ["word0", "word1", "word2", "word3", "word4", "word5", "word6", "word1", "word2", "word3"];
var cQuery = B.ReplaceFirstOccurrencesWithEmpty(A);
string[] c = cQuery.ToArray();
使用LINQ
string[] A = new string[] { "word1", "word2", "word3" };
string[] B = new string[] { "word0", "word1", "word2", "word3", "word4", "word5", "word6", "word1", "word2", "word3" };
string[] result = B.Select((word, i) => i <= A.Length && i > 0 && A[i-1] == word ? "" : word).ToArray();