displaying X number of items from a list - c#

I have a List of Items that I want to print to the console for debugging but I only want to display 3 Items at one time but this is within a function so It needs to know where it left off so it can start from the next 3 items from the previous ones how could I accomplish this?
static void list(Boolean nextPage)
{
static List<Item> _items = new List<Item>();
//if(nextPage) display next page
Console.WriteLine("Press numbers 1 - 3 to display more info on an item or press 4 for next page...\r\n");
int count = 0;
foreach (Item item in _items)
{
Console.WriteLine((count + 1) + ": Name: " + item.itemName + ", ");
count++;
}
Console.WriteLine(("4: Next Page");
}

Make your function non-static, add a variable to store the last item that you have displayed so far, use that variable to decide where to start the next listing, and advance that value by three each time that you go through the function.
Here is a rough approximation to how you can do it - this will probably not work as a copy-paste replacement of your function, but it should give you an idea of what to do:
int lastPosition;
void list(Boolean nextPage) {
if(!nextPage) {
lastPosition = 0;
}
Console.WriteLine("Press numbers 1 - 3 to display more info on an item or press 4 for next page...\r\n");
foreach (Item item in _items.Skip(lastPosition).Take(3))
{
Console.WriteLine((count + 1) + ": Name: " + item.itemName + ", ");
}
lastPosition += 3;
Console.WriteLine(("4: Next Page");
}

Everything created within the scope of a method is trashed when you exit it, unless you return a value toward whoever called the method.
So, you have two choices (or more, but here's two):
private static Item lastItem;
With this, you store inside your class the last item displayed and retrieve it the next time.
or
public static Item itemlist(Boolean nextPage, Item nextItem)
{
// Some logic
return lastItem;
}
And let whoever call your method handle the variable.

Related

Is there a way to match user input string to string in a list and return the index?

I am trying to figure out how to create: A loop that iterates through a list and then displays the index of the item in the list that contains matching text on the screen. Needs to match users input. What I have so far:
List<string> uniqueItems = new List<string>();
{ "Urn of Amen-Ra", "Dyanises Sword", "Pallades Diary", "Ring of Solomon", "Barbar Tea Set" };
Console.WriteLine("Please input text to search in the list: ");
string userItem = Console.ReadLine();
Console.WriteLine("You have ");
for (int d = 0; 0 < uniqueItems.Count; d++)
{
Console.WriteLine(uniqueItems[d]);
break;
}
Just use IndexOf:
List<string> uniqueItems = new List<string>()
{
"Urn of Amen-Ra", "Dyanises Sword", "Pallades Diary",
"Ring of Solomon", "Barbar Tea Set"
};
Console.WriteLine("Please input text to search in the list: ");
string userItem = Console.ReadLine();
Console.WriteLine("You have ");
Console.WriteLine(uniqueItems.IndexOf(userItem));
You seem to have asked two slightly different questions. One is about finding the index of an item, the other is about knowing if an item exists or not
If you want to write these yourself, you need to do some test inside your loop
for (int d = 0; 0 < uniqueItems.Count; d++)
{
Console.WriteLine(uniqueItems[d]);
break;
}
First off you've written 0 < uniqueItems.Count which is always true so this loop will run until the program crashes trying to access an item after the end of the list. Your loop test should read d < ...
But to the point about searching, you need to actually check in the loop whether the item you're looking at is the item you're looking for:
for (int d = 0; 0 < uniqueItems.Count; d++)
{
string lookingAt = uniqueItems[d];
if(lookingAt == userItem){
Console.WriteLine("Found it at index " + d);
break; //exit the loop early
} else {
Console.WriteLine("Didn't find it at index " + d);
}
}
This will print out messages that it didn't find it, until it does m, and then it stops. It is, however, not that useful because as soon as we break out of the loop we lose all knowledge of where the item was, because d disappears when we leave the loop
Instead let's have a variable outside the loop that we can set if we find it. We'll set this variable to -1 to start with because there is no index -1 in a list, so if it stays at -1 when the loop is over we never found it
int foundAt = -1;
for (int d = 0; 0 < uniqueItems.Count; d++)
{
string lookingAt = uniqueItems[d];
if(lookingAt == userItem){
foundAt = d;
break; //exit the loop early
}
}
We don't need that else now because we aren't really interested in items we aren't looking for.
When the loop is over we can examine foundAt to see if it's -1. If it is, we know we never found what we were looking for
if(foundAt == -1)
Console.WriteLine("The list doesn't have the droid you're looking for");
else
Console.WriteLine("The droid you're looking for is in list index " + foundAt);
Microsoft already wrote this code for you in the form of IndexOf and Contains methods but if this is an academic exercise your supervisor will want to see you assemble it yourself. To this end I'm not going to give the whole code but have a play with putting together the snippets given and satisfy yourself that you know how they work

Finding the index of the first gap in a sequence of numbers

I have a problem. It's a bit difficult to explain, but I am going to try. I have a few buttons, which I want to give a sequence. I created a dictionary with the buttons and the SequenceNum. Now when I am in the sequence select screen, I can click a button and give it a number. Now I have this code for getting the next highest number:
foreach (KeyValuePair<string, SelectedHexagonRegistryObject> row in SelectedHexagonRegistry.ToList())
{
if (row.Value.SequenceNum >= NextSequenceNum)
{
NextSequenceNum = row.Value.SequenceNum + 1;
}
}
Now SequenceNum does always get the next highest number, but there is a problem with this. When I gave for example 6 buttons a sequence number and I click 3 again, it gets reset. That is supposed to happen, but when I want to swap numbers for example, I also click the button with the SequenceNum 4. There are 2 buttons with no sequence numbers. If I click one of the 2 buttons that don't have sequence number. The next number is 7. But the problem is that there is a gap, because the numbers 3 and 4 are reset, so I want to be the next number the lowest number of the gap. How can I create something like that?
Example:
I have 6 buttons, which I want to give a sequence number.
When I click the first button it will get SequenceNum 1
Then when I click the rest it will get the highest given number + 1.
At the end I have 6 buttons with all a sequence number from 1 to 6.
When I click for example the button with SequenceNum=4 again, I can unset the SequenceNum to 0 (equals null).
Now when I click that same button another timen, I want it to get the number of the gap that I created, so SequenceNum 4.
Now the problem is that it gets number 7, because it takes the highest + 1.
I need code to fill the gaps and I can't seem to figure out how I can make that!
Something like this should work, unless I am mistaken:
static int GetNextSequenceNo(Dictionary<string, SelectedHexagonRegistryObject> registry)
{
// order the values ascending
var vals = registry.Values.OrderBy(s => s.SequenceNum).ToList();
// find the first value where .SequenceNum is different from (idx + 1)
var firstGap = vals.TakeWhile((s, idx) => s.SequenceNum == idx + 1).Count();
// take the sequenceNum from the previous item and increment
if (firstGap > 0)
return vals[firstGap - 1].SequenceNum + 1;
else
return 1;
}
In general, if you have a list of integers and you want to find the next lowest available number, you can sort them (if they aren't already sorted) and then walk the list one item at a time, comparing the current item to the next item. As soon as you find one where the next item is greater than the current item by more than 1, you have found a gap and can return currentItem + 1.
If you get to the end of the list, then you just return the next number. For example:
private static int GetNextAvailableNumber(IReadOnlyCollection<int> numberSequence)
{
// If the list is null or empty, return the first number (this uses 1, modify as needed)
if (numberSequence == null || !numberSequence.Any()) return 1;
var orderedNumbers = numberSequence.OrderBy(n => n).ToList();
for (var i = 0; i < orderedNumbers.Count - 1; i++)
{
var thisNumber = orderedNumbers[i];
var nextNumber = orderedNumbers[i + 1];
if (nextNumber - thisNumber > 1) return thisNumber + 1;
}
return orderedNumbers.Last() + 1;
}

When second time use function, List is empty

My function working only after compile. When it go second time it doesn't work.
I have function which add new items to my list.
public void addToDetailList()
{
tablist.Add(new OneStudentEvent()
{
Indeks = oneEvent.Indeks,
Parts = oneEvent.Parts,
Present = oneEvent.Present,
PresentcString = oneEvent.PresentString
});
Console.Write("\nCount: " + tablist.Count);
}
And in other function i have return to this tablist.
public List<OneStudentEvent> getDetailEventInfo()
{
Console.Write("\ndb. Count on return: " + tablist.Count);
return tablist;
}
When I compile and run program for first time everything is ok.
But in second time, tablist.Count=0.
Before input to addToDetailList() clear my list:
if(tablist.Count>0)
{
for (int i = tablist.Count - 1; i >= 0; i--)
{
tablist.RemoveAt(i);
Console.Write("\nUSUWAM WIERSZE Z LISTY element: " +i);
}
}
Output:
Count: 5
Count on return: 5
Count: 5
Count on return: 0
getDetailEventInfo is returning a pointer to tablist. That is, it is not generating a new list.
Running var myList = getDetailEventInfo() and then removing items from the tablist means you are removing items from the myList list as well. The are one and the same.
If you change your method to be instead:
return tablist.ToList();
Then you will be returning a brand new list (which is a copy of the source), and your code will work as expected.

Understanding how queue/stack class works and figuring out why this code isn't working

The first foreach method gets several errors. I can't figure out why and it seems like it should work...
foreach - invalid token 'foreach' in class, struct, or interface member declaration.
This prints out 1 2 3 4 1 2 3 4 1 2 3 4.
the 2nd foreach method. How does this work? I think it just iterates through each number one at a time in order. The confusion comes in where it is the same code, but stack instead of queue. The 2nd foreach prints out 4 3 2 1. Why is this?
namespace Cards
{
class Class1
{
Queue numbers = new Queue();
foreach (int number in new int[4]{1,2,3,4})
{
numbers.Enqueue(number);
Console.WriteLine(number + " has joined the queue");
}
foreach (int number in numbers)
{
Console.WriteLine(number);
}
while(numbers.Count > 0)
{
int number = (int)numbers.Dequeue();
Console.WriteLine(number + " has left the queue");
}
}
}
that code needs to be in a method..
class Class1
{
public void DoQstuff()
{
Queue numbers = new Queue();
foreach (int number in new int[4]{1,2,3,4})
{
numbers.Enqueue(number);
Console.WriteLine(number + " has joined the queue");
}
foreach (int number in numbers)
{
Console.WriteLine(number);
}
while(numbers.Count > 0)
{
int number = (int)numbers.Dequeue();
Console.WriteLine(number + " has left the queue");
}
}
}
and the whole thing works as expected if you run it
Queues work, first in, first out..... so 1 was first in, so its first out
Stacks work, first in, last out, so 1 was the first thing in, so it will be the last thing out
like, if you line up to be served at a coffee shop, you have to wait in queue till your turn, first person in the queue, is the first person served.
stacks is like stacking books on top of each other....you can't take the first thing off the stack until you unstack all the things on top of it.
A stack does not follow the same heuristics as a queue. In a queue, what goes in first, also comes out first. In a stack, you're looking at FILO (First In, Last Out).
That is why you see the reverse happening, that is, 4,3,2,1.
Well! In your second loop you are trying to print all the elements in the collection.
1) In case of Queue the objects are stored as it is added. So you get the same answer like in your first loop (FIFO)
2) In case of Stack the objects will be stored in the reverse order so when you pop the object from the collection you can remove the last object which you inserted. (LIFO)
Hope this helps.

C# List Manipulation - Output Different When Stepping Through vs. Running

I'm a C# newbie and I'm really confused about something I'm trying to do for a project in a C# class.
The assignment is some list manipulation in C#.
The program accepts a list of items in the text box, then iterates through those items, creating multiple copies of the list. It randomly resizes each copy of the list to between 3 and all items. It then outputs all the copies.
The problem I'm having is that when I step through this program with the debugger, I get the expected output. The same happens if I display a message box after each iteration (as I have in the code below).
However, if I just run the program straight through, I get a different output. Instead of variations in the lists, all the copies of the list are exactly the same.
If you see in the code I've commented "// FIRST DEBUG MESSAGEBOX" and "// SECOND DEBUG MESSAGEBOX". If the first debug messagebox code is left in there, the output is as expected...multiple versions of the list are output with random lengths between 3 and all items.
However, and this is where I'm confused...if you comment out the first debug messagebox code, you get a different result. All versions of the list output are the same length with no variation.
Any help would be appreciated! Here's the code I have so far...sorry if it's terrible - I'm new at C#:
public partial class MainForm : Form
{
/**
* Vars to hold raw text list items
* and list items split by line
*/
String rawListItems = "";
List<string> listItems = new List<string>();
List<List<string>> textListItems = new List<List<string>>();
public MainForm()
{
InitializeComponent();
}
private void cmdGo_Click(object sender, EventArgs e)
{
// store the contents of the list item text box
this.rawListItems = txtListItems.Text;
this.listItems.AddRange(Regex.Split(this.rawListItems, "\r\n"));
// setup min and max items - max items all items
int minItems = 3;
int maxItems = this.listItems.Count;
// We'll copy this list X times, X = same number of items in list
for (int i = 0; i < this.listItems.Count; i++)
{
// make a copy of the list items
List<string> listItemsCopy = new List<string>(this.listItems);
// get a random number between min items and max items
Random random = new Random();
int maxIndex = random.Next(minItems, maxItems + 1); // max is exclusive, hence the +1
// remove all elements after the maxIndex
for (int j = 0; j < listItemsCopy.Count; j++)
{
if (j > maxIndex)
{
listItemsCopy.RemoveAt(j);
}
}
// add the list copy to the master list
this.textListItems.Add(listItemsCopy);
// FIRST DEBUG MESSAGEBOX
String tst = "";
foreach (string item in listItemsCopy)
{
tst += item + " ## ";
}
MessageBox.Show(tst);
}
// SECOND DEBUG MESSAGEBOX
String output = "";
foreach (List<string> listitem in this.textListItems)
{
foreach (string item in listitem)
{
output += item + " ## ";
}
}
MessageBox.Show(output);
}
}
Move the creation of Random out of the loop:
Random random = new Random();
By default, the constructor uses a default time based seed. In a tight loop, you may be getting 'the same' random generator instead of a different one with each loop.
When using MessageBoxes or single stepping, you are allowing the timer to run and getting 'a new' random generator in each loop.
I don't understand your assignment exactly, but this loop seems to be incorrect:
for (int j = 0; j < listItemsCopy.Count; j++)
{
if (j > maxIndex)
{
listItemsCopy.RemoveAt(j);
}
}
when you remove an element in the middle of a list, elements after that get shifted, so not all the elements after maxIndex get removed, as you might expect.
In circumstances where stepping through the code in a debugger affects the behaviour of the program, a useful alternative debugging technique is to use the System.Diagnostics namespace in particular the Trace class.
The Trace functions work much like Console.WriteLine(), you can trace a string or a format string plus an array of objects to populate the format string, e.g.:
Trace.TraceInformation("some message that tells me something");
Trace.TraceInformation("some useful format string {1}, {0}",
new object[] {someObject, someOtherObject});

Categories

Resources