11

I have a string array like:

 string [] items = {"one","two","three","one","two","one"};

I would like to replace all ones with zero at once. Then items should be:

{"zero","two","three","zero","two","zero"};

I found one solution How do I replace an item in a string array?.

But it will replace the first occurrence only. Which is the best method/approach to replace all occurrences?

3
  • Do you care about order of elements in array? Commented Aug 3, 2012 at 5:26
  • 14
    I wonder how it would be possible to replace without a visit to the item ? Commented Aug 3, 2012 at 5:27
  • @Anirudha Care to elaborate on what you mean by "those optimizations?" Commented Aug 3, 2012 at 5:48

8 Answers 8

40

Theres no way to do that without looping.. even something like this loops internally:

string [] items = {"one","two","three","one","two","one"};

string[] items2 = items.Select(x => x.Replace("one", "zero")).ToArray();

I'm not sure why your requirement is that you can't loop.. however, it will always need to loop.

Sign up to request clarification or add additional context in comments.

2 Comments

Here if items contains "noone" , it will be replaced to "nozero" , rt? I need exactly "one"s to be replaced.
@Praveen: so your original question was wrong? You were not interested in doing it without looping, and you were not interested in replacing all occurrences of one with zero? Is it right to say that Your real question was "how can I replace a string containing only the letters 'one', inside a string array without looping with for/foreach/dowhile"?
14

There is one way to replace it without looping through each element:

 string [] items = {"zero","two","three","zero","two","zero"};

Other than that, you have to iterate through the array (for/lambda/foreach)

Comments

10

Sorry, you have to loop. There's no getting around it.

Also, all of the other answers give you a new array with the desired elements. If you want the same array to have its elements modified, as your question implies, you should just do it like this.

for (int index = 0; index < items.Length; index++)
    if (items[index] == "one")
        items[index] = "zero";

Simple.

To avoid writing a loop in your code every time you need this to happen, create a method:

void ReplaceAll(string[] items, string oldValue, string newValue)
{
    for (int index = 0; index < items.Length; index++)
        if (items[index] == oldValue)
            items[index] = newValue;
}

Then call it like this:

ReplaceAll(items, "one", "zero");

You can also make it into an extension method:

static class ArrayExtensions
{
    public static void ReplaceAll(this string[] items, string oldValue, string newValue)
    {
        for (int index = 0; index < items.Length; index++)
            if (items[index] == oldValue)
                items[index] = newValue;
    }
}

Then you can call it like this:

items.ReplaceAll("one", "zero");

While you're at it, you might want to make it generic:

static class ArrayExtensions
{
    public static void ReplaceAll<T>(this T[] items, T oldValue, T newValue)
    {
        for (int index = 0; index < items.Length; index++)
            if (items[index].Equals(oldValue))
                items[index] = newValue;
    }
}

The call site looks the same.

Now, none of these approaches supports custom string equality checking. For example, you might want the comparison to be case sensitive, or not. Add an overload that takes an IEqualityComparer<T>, so you can supply the comparison you like; this is much more flexible, whether T is string or something else:

static class ArrayExtensions
{
    public static void ReplaceAll<T>(this T[] items, T oldValue, T newValue)
    {
        items.ReplaceAll(oldValue, newValue, EqualityComparer<T>.Default);
    }

    public static void ReplaceAll<T>(this T[] items, T oldValue, T newValue, IEqualityComparer<T> comparer)
    {
        for (int index = 0; index < items.Length; index++)
            if (comparer.Equals(items[index], oldValue))
                items[index] = newValue;
    }
}

Comments

3

You can also do it in parallel:

Parallel.For(0, items.Length,
  idx => { if(items[idx] == "one") { item[idx] = "zero"; } });

Comments

3
string [] items = {"one","two","three","one","two","one"};
items =  items.Select(s => s!= "one" ? s : "zero").ToArray();

Found answer from here.

3 Comments

Note that this creates a new array.
ouch.. Any better solution?
If you have other references to the array it might be important to keep the original array, otherwise your solution is okay of course, but it will loop twice internally. Once for counting the number of items for the array length and once for the replacement. See phoog's answer.
2

You can try this, but I think, It will do looping also.

string [] items = {"one","two","three","one","two","one"};
var str= string.Join(",", items);
var newArray = str.Replace("one","zero").Split(new char[]{','});

Comments

1
string[] items = { "one", "two", "three", "one", "two", "one" };

If you want it the index way as you specified:

int n=0;
while (true)
{
n = Array.IndexOf(items, "one", n);
if (n == -1) break;
items[n] = "zero";
}

But LINQ would be better

var lst = from item in items
select item == "one" ? "zero" : item;

Comments

0
string[] newarry = items.Select(str => { if (str.Equals("one")) str = "zero"; return str; }).ToArray();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.