Iterating array - only array cells with values - c#

What is the way to iterate over (Say a 10 cell) array in c# where only the first 4 are populated with values and avoid going through the remaining 6?
I can keep an int for index and modify it on every array add / remove operation,
but was wondering if c# has a built in (and efficient) function to achieve this.
Thanks in advance.

You have 2 performant options as far is as can tell
A for loop, the downside is you have to check the condition each iteration
for(var i = 0; ary[i] != null & i < length; i++)
{
}
However if this is really mission critical, You will have to keep a list (or index of your range), which slower on update, faster on iteration
If you want to squeze out a bit more performance, use fixed and unsafe

Yes there is, a built in TakeWhile method that you can use:
var result = Array.TakeWhile(item => item != string.IsNullOrEmpty(item));
foreach (int value in result)
{
Console.WriteLine(value);
}

You could use a list and then convert it to an array
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(5);
int[] arr = list.ToArray();
int sum = 0;
foreach (int value in arr)
{
sum += value;
}

I would do something like this with the use of Lambda Expressions.
I made a little console application.
So it checks for nulls and length < 0 will be also a null and then it won't iterate
It won't crash with IndexOutOfRangeException, like the accepted answer
int?[] array = { 6, null, 4, 3, null, };
array.Where(t => t != null).ToList().ForEach(t => Console.WriteLine(t));
Console.ReadLine();

Related

How to iterate a `foreach loop` between index 40-60?

I have a simple question that I can't find a clean answer to when I google.
How do I iterate a foreach loop between index 40-60 and get the values for the indexes?
List<int> list1 = new List<int>();
for (int i = 0; i < 100; i++)
{
list1.Add(i);
}
foreach (var i in list1)
{
//How to iterate between index: 40 to 60 ?
}
The easiest approach would be to use a regular for loop:
for (int i = 40; i < 60; ++i)
{
int value = list1[i];
// Do something with the value
}
Note - if you want to get the value for index 60 too (i.e., the range is inclusive), you should use the <= operator instead of <.
Foreach loop doesn't use an index for traversing an array or collection. They take advantage of the enumerator in an IEnumerable. This answer here has a great explanation of that.
If you want you can add an int before the foreach loop and increment within the loop, but that's all you can do. I would advise that you filter your list1 beforehand and then use it in the foreach loop.
If you really want to use a foreach then you need to write this
List<int> list1 = new List<int>();
foreach(int i in Enumerable.Range(40, 20))
{
list1.Add(i);
}
But, lacking better info on your request to use foreach, then I agree to use a standard for-loop
Aside from other more appropriate answers (e.g. just use a for loop), here's a solution that uses the .Where() overload that provides the index of the element as a parameter to the predicate:
foreach (var i in list1.Where((x, index) => index >= 40 && index <= 60))
{
//How to iterate between index: 40 to 60 ?
}

Turning a for(;;) loop into a foreach

So I've been trying to turn this codes for into a for each, but I keep running into problems, and I'm not all that sure how to do it, the only thing I've done that will work is a small code but it repeats several times, I'm still really new to C# and using for() so I'm not really understanding what to do. Sorry for being so new to this, and I appreciate all the help I can get!
double[] numbers = new double[9.7, 2.2, 4.3, 1.7, 5.6, 3.6, 4.5, 1.3, 4.6, 3.0];
static double ComputeSum(double[] array)
{
double sum = 0;
int intCounter;
for (intCounter = 0; intCounter < array.Length; intCounter++)
{
sum += array[intCounter];
}
return sum;
}
static double ComputeAverage(double[] array)
{
return ComputeSum(array) / array.Length;
}
You got your specific question answered, but not the more general question of "how do I turn a for loop into a foreach?
Let's look at your loop, with some better naming. (Don't name things according to their type in C#. Name things according to their meaning.)
for (index = 0; index< array.Length; index++)
{
sum += array[index];
}
The most important thing is that you understand the idea that this loop represents. A surface level reading is "for every valid index in this array, obtain the element value associated with that index and add it to the sum". But we can make that a bit more abstract. We could also say that the loop means "for every element in the collection, add it to the sum".
That is the key difference between the for loop and the foreach loop. The for loop concentrates on the index, and you fetch the value via the index. The foreach loop concentrates on the value itself, and doesn't consider the index at all.
Knowing that we can now see how to translate a for into a foreach. First locate the bit that is the value, and make a variable for it:
for (index = 0; index < array.Length; index++)
{
var item = array[index];
sum += item;
}
Now we see that the loop body can be expressed almost entirely in terms of an operation on the item, not on the index. We then translate that into a foreach:
foreach (var item in array)
{
sum += item;
}
Everything dealing with the index gets deleted. If you find you cannot delete everything dealing with the index, then you probably should not be using a foreach.
Since foreach loop presents elements of the collection one-by-one to your code, all you need to do is
foreach (double num in Numbers)
{
sump += num;
}
Console.WriteLine("{0}", sump);
You could also use Sum extension method to eliminate loop constructs altogether:
var sump = Numbers.Sum(); // <<== The loop is hidden inside the Sum() method
Console.WriteLine("{0}", sump);

How to add a column of zeros in a List<List<double[]>>()?

I would like to add a column of zeros to all of my double[] in my List<List<double[]>>().
The length of the double[] is currently 2 and I would like to have doubles[] of length 3. The zero should always be in the third position, for example:
double[50, 75] // double [50,75,0]
This has to be done in all of the List<double[]> within List<List<double[]>>.
Is there a short way to do this?
There is a short way of doing this in terms of lines of code, but the number of allocations and copying is equal to the number of arrays in the original list:
var res = orig.
Select(list => list
.Select(array => array.Concat(new[] {0.0}).ToArray())
.ToList()
).ToList();
Demo.
because you want to extend the array in the source list you need to manipulate them in the internal list:
foreach (var list in rootList)
{
for (var i = 0; i < list.Count; i++)
{
var actor = list[i];
list[i] = new double[actor.Length + 1]; // all elements will be 0....
Array.Copy(list[i], actor, actor.Length); //just add the prev elements
}
}
the above operation will apply the change on all pointers to List<List<double[]>>.
if you don't want to make the change on all pointer to rootList, #dasblinkenlight answer is good enough.

Remove list elements at given indices

I have a list which contains some items of type string.
List<string> lstOriginal;
I have another list which contains idices which should be removed from first list.
List<int> lstIndices;
I'd tried to do the job with RemoveAt() method ,
foreach(int indice in lstIndices)
{
lstOriginal.RemoveAt(indice);
}
but it crashes and said me that "index is Out of Range."
You need to sort the indexes that you would like to return from largest to smallest in order to avoid removing something at the wrong index.
foreach(int indice in lstIndices.OrderByDescending(v => v))
{
lstOriginal.RemoveAt(indice);
}
Here is why: let's say have a list of five items, and you'd like to remove items at indexes 2 and 4. If you remove the item at 2 first, the item that was at index 4 would be at index 3, and index 4 would no longer be in the list at all (causing your exception). If you go backwards, all indexes would be there up to the moment when you're ready to remove the corresponding item.
How are you populating the list of indices? There's a much more efficient RemoveAll method that you might be able to use. For example, instead of this:
var indices = new List<int>();
int index = 0;
foreach (var item in data)
if (SomeFunction(data))
indices.Add(index++);
//then some logic to remove the items
you could do this:
data.RemoveAll(item => SomeFunction(item));
This minimizes the copying of items to new positions in the array; each item is copied only once.
You could also use a method group conversion in the above example, instead of a lambda:
data.RemoveAll(SomeFunction);
The reason this is happening is because when you remove an item from the list, the index of each item after it effectively decreases by one, so if you remove them in increasing index order and some items near the end of the original list were to be removed, those indices are now invalid because the list becomes shorter as the earlier items are removed.
The easiest solution is to sort your index list in decreasing order (highest index first) and then iterate across that.
for (int i = 0; i < indices.Count; i++)
{
items.RemoveAt(indices[i] - i);
}
My in-place deleting of given indices as handy extension method. It copies all items only once so it is much more performant if large amount of indicies is to be removed.
It also throws ArgumentOutOfRangeException in case where index to remove is out of bounds.
public static class ListExtensions
{
public static void RemoveAllIndices<T>(this List<T> list, IEnumerable<int> indices)
{
//do not remove Distinct() call here, it's important
var indicesOrdered = indices.Distinct().ToArray();
if(indicesOrdered.Length == 0)
return;
Array.Sort(indicesOrdered);
if (indicesOrdered[0] < 0 || indicesOrdered[indicesOrdered.Length - 1] >= list.Count)
throw new ArgumentOutOfRangeException();
int indexToRemove = 0;
int newIdx = 0;
for (int originalIdx = 0; originalIdx < list.Count; originalIdx++)
{
if(indexToRemove < indicesOrdered.Length && indicesOrdered[indexToRemove] == originalIdx)
{
indexToRemove++;
}
else
{
list[newIdx++] = list[originalIdx];
}
}
list.RemoveRange(newIdx, list.Count - newIdx);
}
}
var array = lstOriginal.ConvertAll(item => new int?(item)).ToArray();
lstIndices.ForEach(index => array[index] = null);
lstOriginal = array.Where(item => item.HasValue).Select(item => item.Value).ToList();
lstIndices.OrderByDescending(p => p).ToList().ForEach(p => lstOriginal.RemoveAt((int)p));
As a side note, in foreach statements, it is better not to modify the Ienumerable on which foreach is running. The out of range error is probably as a result of this situation.

What is fastest way to find number of matches between arrays?

Currently, I am testing every integer element against each other to find which ones match. The arrays do not contain duplicates within their own set. Also, the arrays are not always equal lengths. Are there any tricks to speed this up? I am doing this thousands of times, so it's starting to become a bottle neck in my program, which is in C#.
You could use LINQ:
var query = firstArray.Intersect(secondArray);
Or if the arrays are already sorted you could iterate over the two arrays yourself:
int[] a = { 1, 3, 5 };
int[] b = { 2, 3, 4, 5 };
List<int> result = new List<int>();
int ia = 0;
int ib = 0;
while (ia < a.Length && ib < b.Length)
{
if (a[ia] == b[ib])
{
result.Add(a[ia]);
ib++;
ia++;
}
else if (a[ia] < b[ib])
{
ia++;
}
else
{
ib++;
}
}
Use a HashSet
var set = new HashSet<int>(firstArray);
set.IntersectWith(secondArray);
The set now contains only the values that exist in both arrays.
If such a comparison is a bottleneck in your program, you are perhaps using an inappropriate data structure. The simplest way might be to keep your data sorted. Then for finding out the common entries, you would need to traverse both arrays only once. Another option would be to keep the data in a HashSet.

Categories

Resources