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 Answers
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);
}
}
1 Comment
.Length instead of .Count()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
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 :-)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
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);
Where, btw...)Count()plusLength) 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