【问题标题】:Replace string in the list of string替换字符串列表中的字符串
【发布时间】:2021-05-22 02:05:55
【问题描述】:

我想用下一个列表项字符串替换字符串"$id"。例如,如果列表是

var list = new List<string>()
{
    "test",
    "$id",
    "central",
};

那么列表就会变成

"test"
"central"
"central"

同样,如果列表中只有一项 "$id""$id" 是列表中的最后一项,则它不会被任何内容替换。

我已经创建了以下逻辑

 int index = list.FindIndex(x => x == "$id");
 if (index < list.Count()-1)
 {
    var newList = list.Select(x => x.Replace(list[index], list[index+1])).ToList();
    list = newList;
 }

这是正确的做法还是有更有效的做法。

任何帮助或建议将不胜感激。

【问题讨论】:

  • 如果collection有两个"$id"一个接一个呢?
  • 不,@Fabio 列表中只有 1 个“$id”
  • 在这种情况下,看起来您只需要在 if 块内使用 list[index] = list[index + 1]。另外,在谓词中使用list.IndexOf("$id") 而不是FindIndex()

标签: c# .net list linq replace


【解决方案1】:

对于带有索引器(数组或列表)的集合,您可以在一个循环中完成

for(var i = 0; i < values.Length; i++)
{
    if (i > 0 && values[i - 1] == "$id")
    {
        values[i - 1] = values[i];
    }
}

对于任何类型的集合,您都可以使用枚举器将集合“循环”一次,并且可以访问当前和上一个元素。

下面的方法也支持"$id" 的多次出现。

public static IEnumerable<string> ReplaceTemplateWithNextValue(
    this IEnumerable<string> source, 
    string template
)
{
    using (var iterator = source.GetEnumerator())
    {
        var previous = default(string);
        var replaceQty = 0;
        while (iterator.MoveNext())
        {
            if (iterator.Current == "$id") replaceQty++;

            if (previous == "$id" && iterator.Current != "$id")
            {
                for (var i = 0; i < replaceQty; i++) yield return iterator.Current;
                replaceQty = 0;
            }

            if (iterator.Current != "$id") yield return iterator.Current;

            previous = iterator.Current;
        }

        if (previous == $"$id")
        {
            for (var i = 0; i < replaceQty; i++) yield return previous;
        }
    }
}    

用法

var list = new List<string>() { "test", "$id", "central" };

var replaced = list.ReplaceTemplateWithNextValue("$id");
// => { "test", "central", "central" }

支持的案例:

[Fact]
public void TestReplace()
{
    ReplaceId(Enumerable.Empty<string>()).Should().BeEmpty(); // Pass
    ReplaceId(new[] { "one", "two" })
        .Should().BeEquivalentTo(new[] { "one", "two" }); // Pass
    ReplaceId(new[] { "$id", "two" })
        .Should().BeEquivalentTo(new[] { "two", "two" }); // Pass
    ReplaceId(new[] { "one", "$id", "two" })
        .Should().BeEquivalentTo(new[] { "one", "two", "two" }); // Pass
    ReplaceId(new[] { "one", "two", "$id" })
        .Should().BeEquivalentTo(new[] { "one", "two", "$id" }); // Pass
    Replace(new[] { "one", "$id", "$id" })
        .Should().BeEquivalentTo(new[] { "one", "$id", "$id" }); // Pass
}

【讨论】:

  • 你为什么要删除你对我的回答的评论?
  • @Enigmativity,抱歉,您更新了问题,我认为该评论变得无关紧要。
  • 我总觉得很难理解其他 cmets。现在我给你的回复很混乱。
  • @Enigmativity,到目前为止,我的印象是这是一个“不言而喻”的约定:当您对其他代码发表一些“低重要性”评论并且他们通过更新代码来解决该评论时 - 您只需删除您自己的评论,他们会删除他们的。
  • 我不喜欢需要清除过去的 cmets 以了解如何保持它们在语义上的有效性。恕我直言,这是浪费时间。
【解决方案2】:

这对我有用(前提是列表至少有一个元素):

list =
    list
        .Skip(1)
        .Zip(list, (x1, x0) => x0 == "$id" ? x1 : x0)
        .Append(list.Last())
        .ToList();

【讨论】:

    猜你喜欢
    • 2013-05-01
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 2022-01-02
    • 2013-11-15
    • 2019-01-30
    相关资源
    最近更新 更多