I have a string list and I am continuously adding elements to this list.
I do not want this list to grow beyond 6 elements(index 0 to 5). So once it reaches index[5], I do not want to grow the list, but instead add elements at the start of the list or do something similar to it. At any point, I would be printing the last 3 items added to this list ordered by item last added to this list. I have tried it below but i think it is crappy piece of code. After this piece of code, I would get the list count and print UrlList[UrlList.Count - 1],UrlList[UrlList.Count - 2];,UrlList[UrlList.Count - 3]
Pls help me with it
if (UrlList.Count == 5)
{
var move = UrlList[5];
UrlList.RemoveAt(5);
UrlList.Insert(0, move);
move = UrlList[4];
UrlList.RemoveAt(4);
UrlList.Insert(1, move);
move = UrlList[3];
UrlList.RemoveAt(3);
UrlList.Insert(2, move);
UrlList.Add(uri.ToString());
}
else
{
UrlList.Add(uri.ToString());
}
If you want the latest items to be the last ones in the list, you can use this code:
const int Max_Capacity = 6;
if (UrlList.Count >= Max_Capacity)
UrlList.RemoveAt(0); // <- oldest (first) item should be removed
UrlList.Add(uri.ToString());
...
// Printing out the lastest 3 items:
int start = UrlList.Count <= 3 ? 0 : UrlList.Count - 3;
for (int i = start; i < UrlList.Count; ++i)
Console.Out.WriteLine(UrlList[i]);
I think you better be using % Operator-.
In your case you can use:
UrlList.Insert((UrlList.count%6),move);
Related
so my problem is that I don't know how to go forward in the list and print the next same integer if there is one.
Here is what I have at the moment:
while (list.Contains(input1))
{
Console.WriteLine(input1 + " is at index " + list.IndexOf(input1))
}
I am trying to list all of the integers that are in the list and print the index of them. But not remove after finding one of the integers (this was at least my first idea.).
IndexOf has an overload with two parameters, which allows you to start searching at a later position in the list.
Since this is obviously a learning exercise, I won't spoil it by providing the full code, but rather suggest that you try to implement the following algorithm:
Find the index of input starting at position 0.
If not found (i.e., IndexOf returns -1): we're done. Otherwise:
Print and remember that index.
Start again at step 1, but this time, don't start searching at 0 but at the index you remembered + 1.
You can do the following:
go through the list/array using for statement
for(int i=0; i < list.length; i++) // loop though list
then inside the loop check the value of the current item using if statement:
if(list[i] == input1)
//do smothing
The list[0] represent the first item in the array, which means the index is 0.
so in the example above the i will be the current index so long that you in the loop.
I didn't write the full code for learning purpose in reference to #Heinzi answer.
Hope that could be helpful!
This is an implementation possibility. It is longer than it has to be, but it makes it clearer for beginners how one could tackle this problem.
Since you wanted to only show numbers that come up more than once here is an implementation method. If you want to show numbers that come up only once too just erase everything about lastindex
List<int> yourlist = new List<int> { 1,1,1,1,1,11,2,3,3,4,4,5 };
int input = 0;
input = Convert.ToInt32(Console.ReadLine());
var index = yourlist.IndexOf(input);
//this checks if your input is in the list
var lastindex = yourlist.LastIndexOf(input);
//this does the same but it searches for the last implementation of your input
if (index != -1 && lastindex != index)
//this if checks if your number comes up more than once. IndexOf returns -1 if there is no occurence of your input
{
Console.Write($"the index of {input} is {index}");
for (int i = index+1; i <= yourlist.Count; i++)
//this loop takes the position of the first occurence of your number and then counts up from there
{
var tempindex = yourlist.IndexOf(input, i);
if (tempindex != -1)
//this if lets everything except -1 through
{
Console.Write($" and {tempindex}");
}
}
}
else
{
Console.WriteLine("your number cannot be found twice in the list");
}
I have a list which contains 91 items in it. I currently loop over and write each line to a text file using StreamWriter. I want to divide the list by 3 so after 30 items I want to insert a blank line. So far I have
foreach (var item in textList)
{
//write to file
counter++;
if (counter == totalItems / 3)
{
await sw.WriteLineAsync(Environment.NewLine);
}
}
but it only works for the first 30 items. Please note the list can contain any number of items but this particular one contains 91. However I will always have to divide into 3.
You either want to divide a list of 91 items by 3 or after 30 items. You can't have both. If you do it after every 30 items, you would have the 91st item separated from the rest, on its own 'chunk', i,e. 1-30, 31-60, 61-90, 91. If you have 91 items, and want to split by 3, you should do it every 31 items (hence why I am using Math.Ceiling). That way you'd have 1-31, 32-62 and 63-91.
Also, don't use foreach AND a counter; use the for loop instead. And you can use the modulus operator. As so:
int third = Convert.ToInt32(Math.Ceiling(textList.Count / 3.0));
int divider = third - 1;
for (int i = 0; i < textList.Count; i++)
{
var itemToWrite = textList[i];
//write to file
if (i % third == divider) await sw.WriteLineAsync(Environment.NewLine);
}
Use modulo. Try like:
if (counter % (totalItems / 3) == 0)
{
...
I am trying to filter a list of int based on multiples of a specific number, but I am not sure how to do this. I have searched this forum and found nothing related, but apologies in advance if I'm wrong.
Here is my code:
int val = 28;
List<int> divisible = new List<int>();
for (int i = 1; i <= val; i++) {
divisible.Add(i);
}
foreach(var d in divisible)
{
if(val % d == 0)
{
// do something
}
else
{
// get rid of all multiples of the number that "val" is not divisible by
}
}
Basically, this code should create a divisible list from 1 to 28. If val is divisible by one of the numbers in the list, thats fine, but if it falls into else, I want to be able to filter out all multiples of that number out of the current list we are looping through.
The next number that wouldn't be divisible would be 3 in this example, so in the else get rid of 6, 9, 12, ... etc.
Your code is fine, but you're just missing the actual code to remove the item. But there is a caveat: You cannot modify a list when you are looping through it using foreach. There are a couple ways to handle that:
Depending on your requirements, maybe just don't add them in the first place. Move your val % d == 0 condition into the for loop that adds the values, and just don't add the values that are divisible by d.
Make a new list (List<int> toRemove) where you keep track of all the values you need to remove. After you're done the foreach loop, loop through your toRemove list and use divisible.Remove(value) to remove those.
Change your foreach to a for loop, which will allow you to use divisible.RemoveAt(i). But you will have to make sure you don't skip a value on the next iteration of the for loop (since removing a value changes the size of the list).
I agree with Gabriel. You cannot alter a underlying enumeration while traversing it with with foreach. The easiest thing to do would be to convert it to a for loop.
Also in the initial population of your list try using the newer way
var divisible = Enumerable.Range(1, val).ToList();
then do
for(int 0 = 1; i < val; i++)
{
if(val % d == 0)
{
// do something
}
else
{
divisible.RemoveAt(i);
}
}
Let's say I have a list, messages, with three items. I wan't to loop through them and remove one item at a time.
for (int i = 0; i < messages.Count; i++)
{
messages.RemoveAt(i);
}
(I've removed lots of irrelevant code)
What happen to the remaining messages after the first iteration? Are they moved to another index or can I do it like this to remove all three messages?
Thank you
The index of all elements behind the index you remove will be decremented.
If you want to avoid this with your loop let it run in reverse (delete from highest index to lowest).
for (int i = messages.Count - 1; i >= 0; i--)
{
messages.RemoveAt(i);
}
or just use
messages.Clear()
to delete all elements at once without taking care about any indices.
If you just want to clear the List it's also more efficient to use Clear since it is a O(n) operation. RemoveAt is O(n) as well but inside another O(n) loop which makes it O(n^2) - not that it would matter with 3 elements as mentionend in your example but when talking about larger lists it would certainly make a difference.
In your code, it's simpler to just call messages.Clear();. There's no need to remove each element separately.
Your code will skip every other element as it removes them until the for loop's conditional is no longer met. It will remove the elements at indexes 0 and 2 because you said your collection has three elements.
Let's step through your algorithm:
Initially, the list has three items, listed with their indexes: 0: "Hello", 1: "World", and 2: "Foo".
Your loop removes the element at index 0. The list now looks like this:
0: "World", 1: "Foo"
However, your loop executes again, since i now equals 1 and 1 < 2. The element at index 1 is then removed:
0: "World"
i is incremented to 2 and the conditional is no longer met (i is not less than 1). Your list now consists of what used to be the second element.
You need to iterate backward
for (int i = messages.Count - 1; i >=0; i--)
{
messages.RemoveAt(i);
}
Because in your current loop, you will be left with one time, if your list contains 3 items.
If you want to remove all items from your list then there is a method List<T>.RemoveAll Method
They're moved, see MSDN on List<T>.RemoveAt method:
When you call RemoveAt to remove an item, the remaining items in the
list are renumbered to replace the removed item. For example, if you
remove the item at index 3, the item at index 4 is moved to the 3
position.
To remove all elements, the Clear method is more suitable.
Go thru reverse loop..
for(int i = messages.Count - 1; i >= 0 ; i--) {
messages.RemoveAt(i);
}
You could just changes it to always delete the first one
List<string> messages = new List<string>();
messages.Add("a");
messages.Add("b");
messages.Add("c");
for (int i = 0; i < messages.Count; i++)
{
messages.RemoveAt(0);
}
or to clear whole list in one statement
messages.Clear()
.NET Reference Source has following definition of RemoveAt method:
public void RemoveAt(int index)
{
if ((uint)index >= (uint)_size)
ThrowHelper.ThrowArgumentOutOfRangeException();
Contract.EndContractBlock();
_size--;
if (index < _size)
Array.Copy(_items, index + 1, _items, index, _size - index);
_items[_size] = default(T);
_version++;
}
As you can see - if you remove item which is not last one copying of array items occurs (all items from index + 1 till the end are moved). So in your case its better to remove items from the end to avoid array copying on each iteration:
for (int i = messages.Count - 1; i >= 0; i--)
{
messages.RemoveAt(i);
}
Or simply call messages.Clear() if you want to remove them all without additional logic - in that case internal array just cleared and size set to zero.
Like the other posts, you need to iterate backward
You've got many solutions to remove the items
messages.Clear();
or
while(messages.Count != 0){
message.RemoveAt(0);
}
I've got a DataGrid, which is bound to a List: _bhaList.
Now, I've written a method which will allow the user to select an item on the grid, and move it up. And as it moves up, the No. column is updated to show it's current position. However, in this particular case, where I have 3 items, if I choose No. 2, and move it up, it does switch places with No. 1, and those numbers update, but No. 3 will change to 4. If I repeat the process, the new No. 4 will change to 5.
Here's the code that I've attempted:
var oldIndex = grdBha.SelectedIndex;
var newIndex = oldIndex - 1;
var bha = _bhaList[oldIndex];
_bhaList.RemoveAt(oldIndex);
bha.Number = oldIndex;
_bhaList.Insert(newIndex, bha);
for (var i = newIndex + 1; i <= _bhaList.Count; i++)
{
if (i != _bhaList.Count)
{
_bhaList[i].Number += 1;
}
}
I've tried different variations in the for loop, with no success.
I have the feeling that this is going to be something really simple, but my mind just isn't seeing it.
Your problem is that only two items in this case had their "order changed", yet you incremented the number for everybody below the item moved. In this case Bit X/O Sub was 3, but gets incremented to 4.
You know the only two indices involved:
// swap the two
var temp = _bhaList[newIndex];
_bhaList[newIndex] = _bhaList[oldIndex];
_bhaList[oldIndex] = temp;
_bhaList[newIndex].Number = newIndex + 1;
_bhaList[oldIndex].Number = oldIndex + 1;
If your items can only move one spot at a time the loop is unnecessary and can be replaced with the following:
_bhaList[oldIndex].Number++;
You only need to reshuffle/ swap the locations,
When you _bhaList.Insert(newIndex, bha); it will increment the count by 1.
Try only by replacing those two selected indexes.
Your for loop doesn't make sence, you don't need to increase the number of each items. You only need to do this if you add a new item in the list.
var oldIndex = grdBha.SelectedIndex;
var newIndex = oldIndex - 1;
var oldBha = _bhaList[oldIndex];
var newBha = _bhaList[newIndex];
oldBha.Number--;
newBha.Number++;
_bhaList.RemoveAt(oldIndex);
_bhaList.Insert(newIndex, oldBha);
or
_bhaList[oldIndex] = newBha;
_bhaList[newIndex] = oldBha;
by using
_bhaList.RemoveAt(oldIndex);
bha.Number = oldIndex;
_bhaList.Insert(newIndex, bha);
you have moved the item to the new index. .NET will push down all the other elements as required with out the need for you to do so. As such there is no need for the for loop.
To resolve your issue, simply remove the for loop.