1

I want to get the index of an array which I have done with Array.IndexOf(array, value). This works good with one value but I want to get every occurrence of the value and store the index's into another array. For example, the name 'tom' appears 5 times in an array, I want to find the index positions of each one.

5
  • 5
    It's a task, not a question. What have you tried? What problems have you faced? Commented Mar 31, 2015 at 16:51
  • 2
    (You might want to use LINQ with Where, btw...) Commented Mar 31, 2015 at 16:53
  • 2
    @JonSkeet If he wants the indexes, he doesn't (technically he could, as written by Habib, but it's a pretty big detour) Commented Mar 31, 2015 at 16:53
  • 2
    I don't think it's that much of a detour, to be honest. It says exactly what's needed... Commented Mar 31, 2015 at 17:03
  • No, Ben's code (minus Count() plus Length) is what is needed... Simple, practical, fast and readable by a junior programmer. Using a semi-obscure overload of .Select() to create n temporary objects just to have their index is more like using a cannon to kill an ant. LINQ shouldn't be the solution to all the problems Commented Mar 31, 2015 at 17:11

5 Answers 5

3

Maybe something like this? This uses a list rather than an array, but it follows the same idea.

List<int> Indexes = new List<int>();

for (int i = 0; i < array.Count(); i++)
{
    if (array[i] == "tom")
    {
        Indexes.Add(i);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

You should use .Length instead of .Count()
3

This solution is like the previous one, but will run faster:

string value = "tom";
int[] indices = stringArray.Where(s => s != null)
                           .Select((s, i) => s.Equals(value) ? i: -1)
                           .Where(i => i >= 0)
                           .ToArray();

Comments

2

If I'm not mistaken, you can add another parameter to IndexOf(), which will let you specify where in the array to start. This should give you more or less what you need:

var indices = new List<int>();
int i = Array.IndexOf(array, val);
while(i > -1){
    indices.Add(i);
    i = Array.IndexOf(array, val, i+1);
} 

// ... and if it is important to have the result as an array:
int[] result = indices.ToArray();

Practical example:

var array = new int[]{ 1, 2, 3, 3, 4, 5, 3, 6, 7, 8, 3};
int val = 3;

var indices = new List<int>();    
int i = Array.IndexOf(array, val);
while(i > -1){
    indices.Add(i);
    i = Array.IndexOf(array, val, i+1);
}

// ... and if it is important to have the result as an array:
int[] result = indices.ToArray();

Edit: Just realized a while-loop may well be a lot cleaner than a for-loop for this.


Edit 2: Due to popular demand (see comment below), here`s the original beautiful non-basic for-loop, re-introduced just for your reading pleasure:

for(int i = Array.IndexOf(array, val); i > -1; i = Array.IndexOf(array, val, i+1)){
    indices.Add(i);        
} 

2 Comments

But... but... that non-basic for was so marvelous... it was one of the most beautiful for I had ever seen in the last six months... I had upvoted you only for it :-)
@xanatos Thank you, I feel honored. In fact, I was so deeply moved by your comment, that I have decided to reintroduce the original for-loop. Enjoy! :)
2

Could create an extension method to do it

namespace Extensions
{
    public static class ArrayExtension
    {
        public static IEnumerable<int> GetIndicesOf<T>(this T[] target, T val, int start = 0)
        {
            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
            for (int i = start; i < target.Length; i++)
            {
                if (comparer.Equals(target[i], val))
                {
                    yield return i;
                }
            }
        }
    }
}

Add the using statement for your namespace with the extension method using Extensions; in the file you want to call it in.

Then to call it just do the following to get the indices.

IEnumerable<int> indices = array.GetIndicesOf(value);

or to get an array just do

int[] indicies = array.GetIndicesOf(value).ToArray();

Comments

1

You can use LINQ's Select overload which uses elements index as well, like:

var indices = stringArray.Select((s, i) => new {Value = s, Index = i})
    .Where(r => r.Value == "tom")
    .Select(r => r.Index);

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.