How to retrieve values from Queue using for loop in C#? - c#

class Program
{
static void Main(string[] args)
{
Queue ar = new Queue();
ar.Enqueue(45);
ar.Enqueue(23);
ar.Enqueue(2);
ar.Enqueue(87);
foreach (int x in ar)
{
Console.Write("{0} ", x);
}
Console.ReadLine();
}
}
I know how to retrieve values from a queue using foreach loop. but May I know it is possible to do same thing with the help of for loop ?
I tried following code. but ar[i] is not a valid code. what is the suitable code for ar[i] ?
for (int i = 0 ; i < ar.count ; i++) {
Console.Write("{0} ", ar[i]);
}

It doesn't make much sense to use a for-loop for a Queue since it's not a collection with an index(like IList<T>). So you cannot access items randomly (as with an array: ar[0]). You can use Queue<T>.Dequeue to get the first and remove it or use Queue<T>.Peek to return the first without removing it.
If you used a for-loop you would even get an expected behaviour:
for(int i = 0; i < ar.Count; i++)
Console.Write("{0} ", ar.Dequeue());
Does this display and show all 4 items? No, only the first two because Queue.Count decreases dynamically in the loop whereas the counter variable i increases, hence the loop stops at 2.
So a for-loop is simply the wrong type of loop for this collection. A while is more appropriate:
while(ar.Count > 0)
Console.Write("{0} ", ar.Dequeue());

Related

Nesting loop to get one of each

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.

Output a reserve random list (list function) in C#

I use List function in C# and make it random parameter. This is my code. If it output a list like this: 15 20 10 3 6
How can I output again with the reseve of list above like: 6 3 10 20 15
List<int> dso = new List<int>(20);
Random a = new Random();
for (int i = 0; i < dso.Capacity; i++)
{
int k = a.Next(100);
dso.Add(k);
Console.Write("{0} ", k);
}
for(int i=dso.Capacity;i<20;i--)
{
Console.Write("{0} ", dso[i]);
}
If you're just trying to reverse the list order then use Reverse() like this:
dso.Reverse();
foreach (var number in dso)
{
Console.Write(number + " ");
}
As you appear to be simply writing out the list in full once it's reversed you can use a foreach loop. If however you need more control of where you start in the list or jump around in the list then a for loop is better.
If you want for loop, it should be
for (int i = dso.Count - 1; i >= 0; i--) {
Console.Write("{0} ", dso[i]);
}
Comments:
Count is the number of actual list items; Capacity is reserved memory
List<T> is zero based that's why dso.Count - 1
since you loop in reversed order, condition is i >= 0
However, I suggest using String.Join and Linq instead of loop and let .Net do all the work for you:
// List has its own Reverse() method so we have to put Reverse<int>() to use Linq one
Console.Write(String.Join(" ", dso.Reverse<int>()));

While Looping an Array

I'm trying to understand a book from Don Gosselin on ASP.NET Programming with Visual C#. To solve it I just simply make it to work by adhering to while loops: one while loop is to assign a number to an array element, the other while loop is to display that array. Total array count displays 1 through 100. This should have worked but didn't. Visual Studio 2013 debugger for some reason assigns count = 100, that's why it's failing.
<%
int count = 0;
int[] numbers = new int[100];
while (count <= 100)
{
numbers[count] = count;
++count;
}
while (count <= 100)
{
Response.Write(numbers[count] + "<br />");
++count;
}
%>
You should set count to 0 after first while loop:
int count = 0;
int[] numbers = new int[100];
while (count <= 100)
{
numbers[count] = count;
++count;
}
count = 0;
while (count <= 100)
{
Response.Write(numbers[count] + "<br />");
++count;
}
You need to reset the count to 0 before you attempt the next while statement. Currently, the first loop ends when it reaches a count equal to 101. WHen you proceed to the next while, the count is 101 so the loop automatically ends. Just set count = 0; before the second while loop.
This seems like a very convoluted and unrealistic way of using while loops and arrays. In order to understand it better, it may be worth thinking about it per step.
var i = 0;
while (i < 100)
{
Response.Write(++i + "<br />");
}
The first important distinction is between i++ and ++i. The former utilises the value, and then increments by one; the latter, increments the number and then utilises the value.
In C#, you should really be working with Collections, rather than Arrays. Arrays are zero-indexed, and are renowned for causing serious errors, including exposing potential exploits. Being statically allocated, there is no failsafe when attempting to access indicies outside of the bounds of the Array. Collections, on the other hand, are (for the most part) one-indexed, dynamically allocated, and provide fallbacks when accessing indicies. The most commonly used Collection is a List.
var i = 1;
var list = new List<int>();
while (i <= 100)
{
list.Add(i++);
}
For the second while loop, it's not really suitable to use a while loop here, for any practical example. The excercise is forcing while loops where they are not needed. In this instance, the aim is to iterate through each element in the array (List) and dump its contents to the screen. Because we want to perform an action for each element, a while loop may cause issues. If the array has less than 100 elements, the program will crash, if the array has more than 100 elements, we'll miss some of them. By using a foreach loop, instead of a while, we can eliminate these potential errors.
foreach (var num in list)
{
Response.Write(num + "<br />");
}
Now, I realise that the excercise is about while loops, however, it is teaching you to use them in the wrong way. A much better way - and how you'll most often use them - is to perform an action until a particular condition is met, rather than for simple iteration. By this, I mean, a condition is set to false, then inside the while loop, we manipulate a variable, test the condition, and if it's still false, we go round again. The most common example of this is to work out factorials of numbers.
var num = 5;
var factorial = 1;
while (counter > 1)
{
factorial *= num--;
}
Response.Write(String.Format("{0}! = {1}", input, factorial));
The other main way in which while loops are used is to force an infinite loop, unless a break condition is met. I'll show a very arbitrary use of this here, but a real world example would be the loop() method in Arduino C coding, or a HTTP Listener that constantly repeats the same procedures, until stopped.
var stop = 13;
Response.Write("Pick a number between 1 and 100...<br /><br />");
while (true)
{
var num = new Random().Next(1, 101);
Response.Write(num + " ..... ");
if (num == stop) break;
Response.Write("You got lucky!<br />");
}
Response.Write("Unlucky for you!);
The best way to learn these things is to practice them. Pick a task and find out just how many ways there are to complete it. There is one last important distinction to mention though. a while loop tests the condition at the beginning of the loop. A do while loop, tests the condition at the end.
while(false)
{
// This code will never be run.
}
Compared to:
do
{
// This code will be run once only.
}
while(false)
As a final thought, here's how I'd write the original code (using a LINQ foreach loop):
var numbers = new List<int>();
for (var count = 1; count <= 100; count++)
{
numbers.Add(count);
}
numbers.ForEach(num => Response.Write(num + "<br />")));

Binary search slower, what am I doing wrong?

EDIT: so it looks like this is normal behavior, so can anyone just recommend a faster way to do these numerous intersections?
so my problem is this. I have 8000 lists (strings in each list). For each list (ranging from size 50 to 400), I'm comparing it to every other list and performing a calculation based on the intersection number. So I'll do
list1(intersect)list1= number
list1(intersect)list2= number
list1(intersect)list888= number
And I do this for every list. Previously, I had HashList and my code was essentially this: (well, I was actually searching through properties of an object, so I
had to modify the code a bit, but it's basically this:
I have my two versions below, but if anyone knows anything faster, please let me know!
Loop through AllLists, getting each list, starting with list1, and then do this:
foreach (List list in AllLists)
{
if (list1_length < list_length) //just a check to so I'm looping through the
//smaller list
{
foreach (string word in list1)
{
if (block.generator_list.Contains(word))
{
//simple integer count
}
}
}
// a little more code, but the same, but looping through the other list if it's smaller/bigger
Then I make the lists into regular lists, and applied Sort(), which changed my code to
foreach (List list in AllLists)
{
if (list1_length < list_length) //just a check to so I'm looping through the
//smaller list
{
for (int i = 0; i < list1_length; i++)
{
var test = list.BinarySearch(list1[i]);
if (test > -1)
{
//simple integer count
}
}
}
The first version takes about 6 seconds, the other one takes more than 20 (I just stop there cuz otherwise it would take more than a minute!!!) (and this is for a smallish subset of the data)
I'm sure there's a drastic mistake somewhere, but I can't find it.
Well I have tried three distinct methods for achieving this (assuming I understood the problem correctly). Please note I have used HashSet<int> in order to more easily generate random input.
setting up:
List<HashSet<int>> allSets = new List<HashSet<int>>();
Random rand = new Random();
for(int i = 0; i < 8000; ++i) {
HashSet<int> ints = new HashSet<int>();
for(int j = 0; j < rand.Next(50, 400); ++j) {
ints.Add(rand.Next(0, 1000));
}
allSets.Add(ints);
}
the three methods I checked (code is what runs in the inner loop):
the loop:
note that you are getting duplicated results in your code (intersecting set A with set B and later intersecting set B with set A).
It won't affect your performance thanks to the list length check you are doing. But iterating this way is clearer.
for(int i = 0; i < allSets.Count; ++i) {
for(int j = i + 1; j < allSets.Count; ++j) {
}
}
first method:
used IEnumerable.Intersect() to get the intersection with the other list and checked IEnumerable.Count() to get the size of the intersection.
var intersect = allSets[i].Intersect(allSets[j]);
count = intersect.Count();
this was the slowest one averaging 177s
second method:
cloned the smaller set of the two sets I was intersecting, then used ISet.IntersectWith() and checked the resulting sets Count.
HashSet<int> intersect;
HashSet<int> intersectWith;
if(allSets[i].Count < allSets[j].Count) {
intersect = new HashSet<int>(allSets[i]);
intersectWith = allSets[j];
} else {
intersect = new HashSet<int>(allSets[j]);
intersectWith = allSets[i];
}
intersect.IntersectWith(intersectWith);
count = intersect.Count;
}
}
this one was slightly faster, averaging 154s
third method:
did something very similar to what you did iterated over the shorter set and checked ISet.Contains on the longer set.
for(int i = 0; i < allSets.Count; ++i) {
for(int j = i + 1; j < allSets.Count; ++j) {
count = 0;
if(allSets[i].Count < allSets[j].Count) {
loopingSet = allSets[i];
containsSet = allSets[j];
} else {
loopingSet = allSets[j];
containsSet = allSets[i];
}
foreach(int k in loopingSet) {
if(containsSet.Contains(k)) {
++count;
}
}
}
}
this method was by far the fastest (as expected), averaging 66s
conclusion
the method you're using is the fastest of these three. I certainly can't think of a faster single threaded way to do this. Perhaps there is a better concurrent solution.
I've found that one of the most important considerations in iterating/searching any kind of collection is to choose the collection type very carefully. To iterate through a normal collection for your purposes will not be the most optimal. Try using something like:
System.Collections.Generic.HashSet<T>
Using the Contains() method while iterating over the shorter list of two (as you mentioned you're already doing) should give close to O(1) performance, the same as key lookups in the generic Dictionary type.

for loop ends prematurely when objects are removed

Hi I have a problem with a for loop.
It looks like this
for (int i = 0; i < ObjectManager.Instance.Objects.Count; i++)
{
if (ObjectManager.Instance.Objects[i] is Asteroid)
{
ObjectManager.Instance.Objects.Remove(ObjectManager.Instance.Objects[i]);
}
}
But the count gets shorter while I remove objects, which causes the loop to end prematurely. Is there a way to do this without a bunch of extra loops.
Why don't you loop backward?
// Just change the order from Count - 1 down to 0
for (int i = ObjectManager.Instance.Objects.Count - 1; i >= 0; --i)
{
if (ObjectManager.Instance.Objects[i] is Asteroid)
{
ObjectManager.Instance.Objects.Remove(ObjectManager.Instance.Objects[i]);
}
}
In case you have to loop forward (e.g. if Instances should be deleted in the order they are created because they are depend on each other) you can modify for loop in this way:
for (int i = 0; i < ObjectManager.Instance.Objects.Count;) // <- No increment here
if (ObjectManager.Instance.Objects[i] is Asteroid)
ObjectManager.Instance.Objects.Remove(ObjectManager.Instance.Objects[i]);
else
i += 1; // <- Increment should be here!
Yet another possibility is Linq:
ObjectManager.Instance.Objects.RemoveAll(item => item is Asteroid);
Three options:
If ObjectManager.Instance.Objects is a List<T>, use List<T>.RemoveAll with a predicate, making your code much simpler:
// This replaces your whole loop...
ObjectManager.Instance.Objects.RemoveAll(x => x is Asteroid);
Count from the end of the collection rather than from the start, so that you don't need to adjust the index afterwards:
for (int i = ObjectManager.Instance.Objects.Count - 1; i >= 0; i--)
Just decrement i after calling Remove, so that you'll look at the right index on the next iteration.
Note that in the second and third options your code will be a lot simpler to read if you extract the expression ObjectManager.Instance.Objects into a local variable before you use it 4 times. Also consider using RemoveAt(i) rather than Remove(instances[i]), assuming RemoveAt is available for the type you're using.

Categories

Resources