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 ?
}
Related
I'm trying to make a look to print each of every value once:
Something like this.
Lets pretend that the object letters contains "one,two ...ten"
And then there is the object numbers that contains "1,2,3,4...10"
Now if I want the loop to print:
One
1
Two
2
Three
3
How would the loop look like?
I tried it like this:
foreach (var i in letters)
{
Console.WriteLine(i);
foreach(var a in numbers)
{
Console.WriteLine(a);
}
}
But this returns:
One
1
2
Two
1
2
Three
1
2
And that result isn't what I want..
How can I nest the loops to make it print the way I want it?
Maybe you can use IEnumerable<T>.Zip(...), see here, to make combinations.
var data = letters.Zip(numbers, (l, n) => new { letter = l, number = n})
foreach (var item in data) {
Console.Writeline(item.letter);
Console.Writeline(item.number);
}
use forloop insted of foreach use it like this
for (int i=0;i<letters.length;i++)
{
Console.WriteLine(letters[i]);
Console.WriteLine(numbers[i]);
}
Don't do two nested loops, they are for enumerating over all possible pairs from two collections.
Instead, make a loop on the index, and use it for both collections, or use LINQ's Zip method:
foreach (var pair in letters.Zip(numbers, (l, n) => new {Letter=l, Number=n})) {
Console.WriteLine("{0} - {1}", pair.Letter, pair.Number);
}
Assuming your Numbers and Letters are collections that derive from IEnumerable, you could do something like this:
var zipped = letters.Zip(numbers, Tuple.Create);
foreach (var tuple in zipped)
{
Console.WriteLine(tuple.Item1);
Console.WriteLine(tuple.Item2);
}
You need a single loop to iterate over both lists:
for (int index = 0; index < letters.Count; index++)
{
Console.WriteLine(letters[index]);
Console.WriteLine(numbers[index]);
}
This presupposes that your lists are the same length. If they're not you'd have to set the upper limit to the length of the shorter list.
for (int index = 0; index < Math.Min(letters.Count, numbers.Count); index++)
You're close - the second loop should not be within the first, but you should use one loop to iterate over both arrays. Try:
for (int i = 0; i < letters.size(); i++) {
Console.WriteLine(letters.getItem(i));
Console.WriteLine(numbers.getItem(i));
}
Note that this assumes a size() method to return the number of items and a getItem() method to return a specific item from the object.
What's happening is that for every time your outside loop runs, the inside one runs twice.
That's because your loops are nested, there's no getting around this.
If you absolutely must use nested loops for this, you'd have to add a check whether your number has been printed yet
Something like:
foreach(var i in letters)
{
Console.WriteLine(i);
foreach(var a in numbers)
{
if (a.isPrinted) //if it has been printed already
{
continue; //skip ahead
}
else
{
Console.WriteLine(a.number);
a.isPrinted = true;
break; //stop and jump out of the foreach loop
}
}
}
This also means that each number is actually an object that holds the bool isPrinted and int number
I wouldn't doing it like that, it's ridiculously inefficient.
You should do what others have already suggested.
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);
I can use 'foreach' for iteration Hashtable, but i need in use cycle with index (for)
I use this:
int i = 0;
foreach (var field in Hashtable) {
i++;
//action
}
but i think this is not good
I NEED CYCLE 'FOR'
For loops are useful for collections that can be indexes by numbers.
Therefore the only useful way to iterate over a HashTable is to iterate over the Hashtables keys.
var keys = hashtable.Keys.ToArray();
for (int i = 0; i < keys.Length; i++)
var value = hashtable[keys[i]];
When i is even, do something, and when i is odd do something else.
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.
I have a list of numbers and I’d like to remove all the even ones. I think my code is right:
System.Collections.Generic.List<int> list = ...
foreach (int i in list)
{
if (i % 2 == 0)
list.Remove(i);
}
but when I run it I get an exception. What am I doing wrong?
You can't modify a collection in a foreach loop, that being said,
you can't remove an item from a list that you're iterating over in a foreach loop.
Instead of the foreach loop, just use this single line of code:
list.RemoveAll(i => i % 2 == 0);
You cannot modify the collection during a foreach loop. A foreach loop uses an enumerator to loop through the collection, and when the collection is modified this is what happens to the enumerator:
An enumerator remains valid as long as the collection remains
unchanged. If changes are made to the collection, such as adding,
modifying, or deleting elements, the enumerator is irrecoverably
invalidated and its behavior is undefined.
You can use a regular for loop.
for (int i = 0; i < list.Count; i++)
{
int n = list[i];
if (n % 2 == 0)
{
list.RemoveAt(i--);
}
}
The foreach uses an IEnumerator under the covers, when an element in your list is removed, it leaves the enumerator in a potentially inconsistent state. The 'safest' thing for it to do is throw an exception.
To work around this, make a local copy of your collection first:
var local = new List<int>(list);
foreach (int i in local) { if (i % 2 == 0) list.Remove(i); }
If you're removing from a list of anything (or even an array) you should iterate backward through it as removing an item shifts all items after it down by one position. Iterating forward will cause you to skip over the next item each time.
Which exception did you get? Sometimes foreach will lock an item to where it can't be edited when it's used in the foreach. Instead, use for (and go backwards!)
for(int i = list.Length - 1 ; i > -1 ; i--)
to follow #Chris Filstow's method....
this will take your list, and replace it with a new one where the elements meet your criteria:
System.Collections.Generic.List<int> list = ...
list = list.Where( n=> n % 2 == 0 ).ToList();
You could try something like this instead. (It creates a new list of just the even numbers rather than removing the odds from the existing list, so it depends on what you're looking to do.)
var numbers = Enumerable.Range(1, 100);
var evens = numbers.Where(n => n % 2 == 1);
All your getting out of the foreach loop is readonly if you try to change the items in the list it explains why you get an exception.
This article right here explains why.
You could alway switch to a for loop.
for (int i = 1 ; i < list.lenght; i++)
{
if (i % 2 == 0)
list.Remove(i);
}