Iterate and modify Dictionary - c#

I am trying to implement solution for problem explined on http://users.metropolia.fi/~dangm/blog/?p=67.
I am new to c# language.I want to iterate through the dictionary using enumerator and for a particular condition.So there are two variables current and previous.current points to first element of dictionary.previous points to previous element in dictionary.While iterating over dictionary I am iterating like foll
previous=current;
current.MoveNext();
The problem is when we iterate first time thru whole dictionary previous points to last element in dictionary and current points to random keyvalue pair RawVariable(0,0).But now for when we iterate second time through dictionary i want current to point to first element in dictionary.how do i make current point to some element that has a particular key or value
Here is my code snippet
public void falling_disks(int[] A, int[] B)
{
Dictionary<int, int> filledDictionary = filldictionary(d1, A);
//previous stores the previous element in dictionary
var previous = filledDictionary .GetEnumerator();
//current stores next element of previous
var current = filledDictionary .GetEnumerator();
current.MoveNext();
//for each incoming element in array B
foreach (int ele in B)
{
//check if the current key is filled in hashtable h1 that is check if it
//is already added
if (!checkifthatvalueisfilled(current.Current.Key))
{
//if not check if current value is less than or equal to element
while ((current.Current.Value >= ele))
{
//assign previous to current
previous = current;
//move current to next position
current.MoveNext();
}
listofitemstoremove.Add(previous.Current.Key);
}
else
{
listofitemstoremove.Add(current.Current.Key);
}
foreach (int item in listofitemstoremove)
{
if (!(h1.ContainsKey(item)))
h1.Add(item, true);
}
}
Console.WriteLine(listofitemstoremove.Capacity);
}
public bool checkifthatvalueisfilled(int key)
{
if (h1.ContainsValue(h1.ContainsKey(key)) == true)
return true;
else return false;
}
}

Your question is difficult to understand. Perhaps this is what you want to do at the beginning of your loop?
current = h1.GetEnumerator();
current.MoveNext();

If i understood your question correctly, you cant do it. Enumerator gives you consecutive access to the collection, that's the whole point. You cant suddenly move it to the particular element, without iterating to that element from the beginning.
Futheremore i dont see a single good reason to use enumerator. If you need refs to previous and current elements for your algorithm - you should store their keys, not enumerators. Also im pretty sure that these lines
while ((current.Current.Value >= ele))
{
//assign previous to current
previous = current;
//move current to next position
current.MoveNext();
}
a) will throw an exception, when you ll reach the end of the collection b) wont work as expected since you are assigning reference types

I'm not sure that I understand your question, but perhaps you want to change this:
previous = current;
To this:
previous.MoveNext();
That way 'previous' will always be one step behind 'current'. If you assign the variables the way you do in the original code, you just have two references to the 'current' object which is then incremented.

Related

C# sort List<int> recursively

there's an exercise i need to do, given a List i need to sort the content using ONLY recursive methods (no while, do while, for, foreach).
So... i'm struggling (for over 2 hours now) and i dont know how to even begin.
The function must be
List<int> SortHighestToLowest (List<int> list) {
}
I THINK i should check if the previous number is greater than the actual number and so on but what if the last number is greater than the first number on the list?, that's why im having a headache.
I appreciate your help, thanks a lot.
[EDIT]
I delivered the exercise but then teacher said i shouldn't use external variables like i did here:
List<int> _tempList2 = new List<int>();
int _actualListIndex = 0;
int _actualMaxNumber = 0;
int _actualMaxNumberIndex = 0;
List<int> SortHighestToLowest(List<int> list)
{
if (list.Count == 0)
return _tempList2;
if (_actualListIndex == 0)
_actualMaxNumber = list[0];
if (_actualListIndex < list.Count -1)
{
_actualListIndex++;
if (list[_actualListIndex] > _actualMaxNumber)
{
_actualMaxNumberIndex = _actualListIndex;
_actualMaxNumber = list[_actualListIndex];
}
return SortHighestToLowest(list);
}
_tempList2.Add(_actualMaxNumber);
list.RemoveAt(_actualMaxNumberIndex);
_actualListIndex = 0;
_actualMaxNumberIndex = 0;
return SortHighestToLowest(list);
}
Exercise is done and i approved (thanks to other exercises as well) but i was wondering if there's a way of doing this without external variables and without using System.Linq like String.Empty's response (im just curious, the community helped me to solve my issue and im thankful).
I am taking your instructions to the letter here.
Only recursive methods
No while, do while, for, foreach
Signature must be List<int> SortHighestToLowest(List<int> list)
Now, I do assume you may use at least the built-in properties and methods of the List<T> type. If not, you would have a hard time even reading the elements of your list.
That said, any calls to Sort or OrderBy methods would be beyond the point here, since they would render any recursive method useless.
I also assume it is okay to use other lists in the process, since you didn't mention anything in regards to that.
With all that in mind, I came to this piece below, making use of Max and Remove methods from List<T> class, and a new list of integers for each recursive call:
public static List<int> SortHighestToLowest(List<int> list)
{
// recursivity breaker
if (list.Count <= 1)
return list;
// remove highest item
var max = list.Max();
list.Remove(max);
// append highest item to recursive call for the remainder of the list
return new List<int>(SortHighestToLowest(list)) { max };
}
For solving this problem, try to solve smaller subsets. Consider the following list
[1,5,3,2]
Let's take the last element out of list, and consider the rest as sorted which will be [1,3,5] and 2. Now the problem reduces to another problem of inserting this 2 in its correct position. If we can insert it in correct position then the array becomes sorted. This can be applied recursively.
For every recursive problem there should be a base condition w.r.t the hypothesis we make. For the first problem the base condition is array with single element. A single element array is always sorted.
For the second insert problem the base condition will be an empty array or the last element in array is less than the element to be inserted. In both cases the element is inserted at the end.
Algorithm
---------
Sort(list)
if(list.count==1)
return
temp = last element of list
temp_list = list with last element removed
Sort(temp_list)
Insert(temp_list, temp)
Insert(list, temp)
if(list.count ==0 || list[n-1] <= temp)
list.insert(temp)
return
insert_temp = last element of list
insert_temp_list = list with last element removed
Insert(insert_temo_list, insert_temp)
For Insert after base condition its calling recursively till it find the correct position for the last element which is removed.

Concise way to get the single element contained in a HashSet, C#

I know for sure that at a particular point in my program a HashSet I've constructed will only contain a single element. I know I can get the element by doing this:
foreach (int num in myHashSet)
{
return num;
}
But I don't like the idea of using a for loop when I'm certain that the HashSet only contains a single item. I know HashSets are unordered and understand why using, say, an array-style index won't work. Are there any solutions that will make it clear that only a single element exists in the HashSet? I feel that with a loop this property isn't clear.
HashSet<int> ihs = new HashSet<int>();
ihs.Add(12);
if (ihs.Count() == 1)
{
int x = ihs.First();
}

Removing an object from a list in a foreach loop of that list

I have made a method that eliminates any replicates of the same string in a List.
now, the problem is that it gives me this error:
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
I read in the internet, and i think that the problem is the i am removing an object from the list inside the foreach loop of the list.
foreach (string r in list)
{
int numberOfAppearance=0;
foreach (string rs in list)
{
if (r == rs && numberOfAppearance> 0)
list.Remove(rs);
else
numberOfAppearance++;
}
}
How can i fix the method? Thanks for the help
Firstly, as noted in comments, LINQ has got you covered here:
list = list.Distinct().ToList();
It's well worth looking into LINQ for data operations - it can make things much simpler.
As for what's wrong with your current code - there are a couple of things:
Firstly, you're removing by item rather than by index, which will remove the first occurrence of that item, not the one you're actually looking at
Secondly, if you modify a list while you're iterating over it, you will get precisely the exception you've seen. From the docs for List<T>.GetEnumerator:
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 get around this by iterating by index rather than using a foreach loop, but if you're removing an item you need to remember that everything below that will move up one element. So either you need to iterate backwards to remove items, or you need to remember to decrement the index.
Here's an approach which uses iterating by index forwards in terms of what we're looking at, but backwards in terms of looking for duplicates - stopping when we get to the index we're looking at. Note that this is still O(N2) - it's not as efficient as using Distinct:
// We're looking for duplicates *after* list[i], so we don't need to go as far
// as i being the very last element: there aren't any elements after it to be
// duplicates. (We could easily still just use list.Count, and the loop for j
// would just have 0 iterations.)
for (int i = 0; i < list.Count - 1; i++)
{
// Go backwards from the end, looking for duplicates of list[i]
for (int j = list.Count - 1; j > i; j--)
{
if (list[j] == list[i])
{
list.RemoveAt(j);
}
}
}
(For more details on Distinct, see my Edulinq post on it.)
As many people point out, you can use the Distinct method for your particular problem.
However, the problem you are actually having is that you are trying to modify the list when you iterate over it, which will not end well.
//This will not work.
foreach (string rs in list)
{
if (some_test)
{
list.Remove(rs); //Because of this line.
}
}
If you want do do something similar to this you need to find a way around this problem. Often it involves making a new array.
For this examle you can do the following
List newList = new ArrayList();
foreach (string rs in list)
{
if (!some_test)
{
newList.add(rs);
}
}
If you really want to create a "remove duplicates" method I would have done it in this fashion (pseudocode):
Hash cache_hash = new Hash(default false)
List new_list = new List
foreach string s in list
{
if not cache_hash[s]
{
new_list.add(s)
cache_hash[s] = true
}
}
list = new_list
This method is Ω(N) , so it is fairly fast on even large lists.

How to get the previous value in a list of strings in c#?

I'm trying to implement a previous and next buttons.
I have a list of string called list1 which is filled with whatever is a user has inputted from a textbox. I can't access the previous (not the last) string in the list. IndexOf method isn't useful as I don't know what user will input.
private void previousBtn_click(object sender, EventArgs e)
{
getList();
int min = 0;
int max = list1.Count;
if(max==min)
{
previousBtn.Visible = false;
}
else
{
int temp =list.Count-1;
//how do I get my string if I know the element index from the previous line?
//textbox1.Text = thatPreviousString;
}
}
Sorry, it should be easy but I can't figure it out. How can I actully get my previous string in the list if the value is kind of unknown to me, so I can't just use find() and indexOf.
MSDN shows that there is a property called Item but there is no proper tutorial or code bit that shows how to use it.
UPDATE:
Let's say the user has typed "www.google.com", "www.facebook.com", "twitter.com" and then "www.yahoo.com". This urls are saved in list1. The last one was "www.yahoo.com", I can get it by calling Last(). The user can press the previous button anytime, so I can't specify the number of elements in list1, it's growing dynamically. I can only get the number of elements by calling
list1.Count and the last index by calling list1[list1.Count-1]
Now I know the number of indexes and elements, so how do I get the previous string, e.g. "www.twitter.com", if I can only say I can give you the index, give my string back?
By the way, ElementAs is only for arrays, doesn't work for lists.
how do I get my string if I know the element index from the previous line?
int prevIndex; // element index from the previous line that you know
string temp = list1[prevIndex - 1];
string temp =list[list.Count-1]; will give you the last element in the list.
string temp =list[list.Count-2]; will give you the previous element.
Remember, lists are 0-indexed, ie the first element is accessed via [0], so the last element will be [list size - 1].
So in your case textbox1.Text = list[list.Count-2]; will write the previous string into the textbox.
However, that won't give you a proper previous functionality. Pressing previous again won't give you list[list.Count-3]. You could though have a currentIndex variable that you decrement whenever previous is pressed for example and do textbox1.Text = list[currentIndex].

Bubblesort implementation using linked-list only partially works

I am trying to use bubble sort to sort a list of items. I am aware that this is not the most effective method of sorting; however, I require this method to work before moving on to better things. My current code partially sorts a list, but I cannot see what I am doing wrong.
public class ListComponents
{
public int Priority;
public string Name;
public ListComponents Next;
}
public void bubblesort()
{
ListComponents Current = Head;
int temp = 0;
bool swapped = true;
while (swapped)
{
Print(); // Debug Function to print each swap
Current = Head.Next; // RESET CURRENT TO HEAD + 1 ON EACH ITERATION?
swapped = false;
for (int sort = 0; sort < (size - 1); sort++) //Size defined as # of items in list
{
if (Current != null &&
Current.Next != null &&
Current.Priority> Current.Next.Priority)
{
temp = Current.Priority;
Current.Priority= Current.Next.Priority;
Current.Next.Priority= temp;
Current = Head; // POTENTIAL ISSUE?
swapped = true;
}
}
}
}
My debug print function shows the following, showing how the values are almost in order:
List: 4 2 1 3 (Inital List Order)
List: 1 4 2 3 (First Swap)
List: 1 2 4 3 (Second Swap)
The issue seems to be with setting the 'Current' value, although I cannot see where this is not working.
My advice: start over. This is a mess.
Here's how I would tackle problems like this when I was a beginner. Start by writing the code in pseduo-code:
void BubbleSort(ListComponent head)
{
if the list is of zero length then it is already sorted, so return
if the list is of length one then it is already sorted, so return
Otherwise, the list is of length two or more. Therefore we know that
a first item exists and a second-last item exists.
Our strategy is: run down the list starting with the first item
and ending with the second-last item. If at any time the current
item and the one following it are out of order, swap their elements.
If we made no swaps then the list is sorted, return.
If we made one or more swaps then the list might not be sorted, so
run down the list again.
}
OK, now we can start translating that into code.
void BubbleSort(ListComponent head)
{
// if the list is of zero length then it is already sorted, so return
if (head == null) return;
// if the list is of length one then it is already sorted, so return
if (head.Next == null) return;
// Otherwise, the list is of length two or more. Therefore we know that
// a first item exists and a second-last item exists.
// Our strategy is: run down the list starting with the first item
// and ending with the second-last item.
for (ListComponent current = head;
current.Next != null;
current = current.Next)
{
If at any time the current item and the one following it
are out of order, swap their elements.
}
If we made no swaps then the list is sorted, return.
If we made one or more swaps then the list might not be sorted, so
run down the list again.
}
OK, I've translated some of that English into code. Can you translate the rest?
Another example with a simple class with 2 properties. This is NOT for arrays but for a simple class simulating pointers... Made just for fun !
class MyLinkedList
{
MyLinkedList nextNode;
int data;
public void OrderListBubbleAlgoritm(ref MyLinkedList head)
{
bool needRestart = true;
MyLinkedList actualNode = head; //node Im working with
int temp;
while (needRestart)
{
needRestart = false;
actualNode = head;
while (!needRestart && actualNode.nextNode != null)
{
if (actualNode.nextNode.data >= actualNode.data) //is sorted
{
actualNode = actualNode.nextNode;
}
else
{
//swap the data
temp = actualNode.data;
actualNode.data = actualNode.nextNode.data;
actualNode.nextNode.data = temp;
needRestart = true;
}
}
}
}
}
Remember to use bubble sorting just with small quantity of data.
It's performance is: O(n^2)

Categories

Resources