For collections with indexers(Array or List), you can do it in one loop
for(var i = 0; i < values.Length; i++)
{
if (i > 0 && values[i - 1] == "$id")
{
values[i - 1] = values[i];
}
}
For any type of collection you can use enumerator to "loop" the collection only once and have access to current and previous element.
Approach below supports multiple occurrences of "$id" as well.
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;
}
}
}
Usage
var list = new List<string>() { "test", "$id", "central" };
var replaced = list.ReplaceTemplateWithNextValue("$id");
// => { "test", "central", "central" }
Supported cases:
[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
}
"$id"one after another?list[index] = list[index + 1]inside theifblock. Also, uselist.IndexOf("$id")instead ofFindIndex()with a predicate.