When second time use function, List is empty - c#

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.

Related

How to find repetitions/duplicates in the array within 10 elements apart

I have an array like following:
{1,5,5,4,5,6,7,8,9,10,11,12,13,14,1,16,17,5}
I want to find duplicates within each 10 elements from one to another.
I need a code that can tell me that 5 was duplicated 3 times within 10 elements (there are at most only 1 element between 5s (4). It should igore last 5 as it is too far away. Only three 5s are within 10 elements).
I don't want code to return 1, because there are 13 element in between both 1s.
I have a code that can count duplicates but how to change it so it can count duplicates withing 10 elements?
var dict = new Dictionary<string, int>();
foreach (var count in combined2)
{
if (dict.ContainsKey(count))
dict[count]++;
else
dict[count] = 1;
}
foreach (var val in dict)
{
MessageBox.Show(val.Key + " occurred " + val.Value + " times");
}
I'm only concerned with duplicates that occur the most. If some number get duplicated twice but another gets duplicated 3 times. I would only like to know about number that got duplicated 3 times (withing 10 items). Thank you
Make a dictionary max defaulting to 0
Make a dictionary seen defaulting to 0
Count count from 0 up to N, where N is number of elements.
after N >= 10, decrement seen[array[count - 10]]
Increment seen[array[count]]
If that number is higher than max[array[count]], update it
Repeat
Return the key of the highest value in max.
This way, seen always has the accurate count in the 10-element window, and max will have the maximum number of appearances of each element in a 10-element window.
This code finds the first item with the higher number of occurrences inside the "numbers" array (within n = 10 elements):
int n = 10;
int[] numbers = new int[] {1,5,5,4,5,6,7,8,9,10,11,12,13,14,1,16,17,5};
int mostDuplicatedNumber = 0, numberOfMaxOccurrences = 0;
for(int count = 0; count < numbers.Length - n; count++)
{
var groupOfNumbers = numbers.Skip(count).Take(n).GroupBy(i => i).OrderByDescending(i => i.Count());
if(numberOfMaxOccurrences < groupOfNumbers.First().Count())
{
numberOfMaxOccurrences = groupOfNumbers.First().Count();
mostDuplicatedNumber = groupOfNumbers.First().Key;
}
}
Console.WriteLine("Most duplicated number is " + mostDuplicatedNumber + " with " + numberOfMaxOccurrences + " occurrences");
Try out this way. I have not tested using IDE just wrote while travelling. Let me know if you encounter any error. What it does simply take first 10 elements and finds number of occurrence i.e. repetition but then ( you would like to display most repeated number in that case you have to hold those repeated numbers in another array and swap the elements to get most repeated and least repeated one as you asking in your question I have not implemented this part ) .
.................
int[] inputArray= {1,5,5,4,5,6,7,8,9,10,11,12,13,14,1,16,17,5} // total input elements
int[] mostAndLeastOccuranceArray=new int[10] ;
int skip=0;
int limit=10;
int[] resultArray=new int[10];
for (int i = skip; i < inputArray.Length; i++)
{
if(i<limit)
{
resultArray[i]=inputArray[i];
skip=skip+1;
}else
{
findOccurance(resultArray); // call in every 10 elements array subset
resultArray=new int[10]; // re-initialize the array
limit=limit+10; // increase the limit for next iteration remember loop has not finished yet
}
}
public void findOccurance(int[] resultArray)
{
var dict = new Dictionary < int,int > ();
foreach(var value in resultArray)
{
if (dict.ContainsKey(value)) dict[value]++;
else dict[value] = 1;
}
foreach(var pair in dict)
{
mostAndLeastOccuranceArray[pair.Key]=pair.Value; // store the repeated value
Console.WriteLine("Value {0} occurred {1} times", pair.Key, pair.Value);
}
// call the method to find most and least occurance elements within each array subsets
findMostAndLeastOccuranceElements(mostAndLeastOccuranceArray)
// re-initialize
mostAndLeastOccuranceArray=new int[10] ;
}
public void findMostAndLeastOccuranceElements(int[] mostAndLeastOccuranceArray)
{
// now find most and least repeated elements within each 10 elements block
}
A simpler solution would be to use LINQ. Here I wrote a simple method to count the number of time a value is repeated.
public int CountRepetitions(List<int> myLists,int maxValues,int number)
{
if (myLists.Count > maxValues)
return myLists.Take(maxValues).Count(v => v == number);
else return 0;
}

Variable number of for loops without recursion but with Stack?

I know the usual approach for "variable number of for loops" is said to use a recursive method. But I wonder if I could solve that without recursion and instead with using Stack, since you can bypass recursion with the use of a stack.
My example:
I have a variable number of collections and I need to combine every item of every collection with every other item of the other collections.
// example for collections A, B and C:
A (4 items) + B (8 items) + C (10 items)
4 * 8 * 10 = 320 combinations
I need to run through all those 320 combinations. Yet at compile time I don't know if B or C or D exist. How would a solution with no recursive method but with the use of an instance of Stack look like?
Edit:
I realized Stack is not necessary here at all, while you can avoid recursion with a simple int array and a few while loops. Thanks for help and info.
Not with a stack but without recursion.
void Main()
{
var l = new List<List<int>>()
{
new List<int>(){ 1,2,3 },
new List<int>(){ 4,5,6 },
new List<int>(){ 7,8,9 }
};
var result = CartesianProduct(l);
}
static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>()};
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] {item})
);
}
Function taken form Computing a Cartesian Product with LINQ
Here is an example of how to do this. Algorithm is taken from this question - https://stackoverflow.com/a/2419399/5311735 and converted to C#. Note that it can be made more efficient, but I converted inefficient version to C# because it's better illustrates the concept (you can see more efficient version in the linked question):
static IEnumerable<T[]> CartesianProduct<T>(IList<IList<T>> collections) {
// this contains the indexes of elements from each collection to combine next
var indexes = new int[collections.Count];
bool done = false;
while (!done) {
// initialize array for next combination
var nextProduct = new T[collections.Count];
// fill it
for (int i = 0; i < collections.Count; i++) {
var collection = collections[i];
nextProduct[i] = collection[indexes[i]];
}
yield return nextProduct;
// now we need to calculate indexes for the next combination
// for that, increase last index by one, until it becomes equal to the length of last collection
// then increase second last index by one until it becomes equal to the length of second last collection
// and so on - basically the same how you would do with regular numbers - 09 + 1 = 10, 099 + 1 = 100 and so on.
var j = collections.Count - 1;
while (true) {
indexes[j]++;
if (indexes[j] < collections[j].Count) {
break;
}
indexes[j] = 0;
j--;
if (j < 0) {
done = true;
break;
}
}
}
}

Splitting List based on element variable and element position

hey I'm trying to split a list based on if a bool of the element is true or not. but each time it has passed some true's and encounters a false i want it also to start a new list with the all the false until it encounters true again and so on. so basicly grouping sequences of falses and trues
public void SortWalls()
{
List<Node> innerWallNodes;
foreach(Wall w in walls)
{
WallAxis ax = w.axis;
innerWallNodes = new List<Node>();
for(int i=w.wallNodes.Count-1; i>=0; i--)
{
if(w.wallNodes[i].markedForDoor)
{
//split wall!!
innerWallNodes.Add(w.wallNodes[i]);
w.wallNodes.RemoveAt(i);
}
}
if(innerWallNodes.Count > 0)
{
Wall wall = new Wall(innerWallNodes, ax);
innerWalls.Add(wall);
}
}
}
i did it like this and then build a mesh based on the first and last element of a List. but since there are many scenarios where the innerWallNodes could be somewhere in the middle of the list that get "cut out" and so my remaining "outer wall" would still have the same node index in my grid for the first and last in it's list, still overdrawing my "inner wall"
so lets say every node !markedForDoor is 0 and a every node markedForDoor is 1 and they order something like below in my list.
like this:
|000|11111|00000|11|000| how would i get a list for every between |...| ?
how do i do this in a simple way. I thought Linq would have something for this but can't find anything.
Linq won't help. Here is the code:
List<List<YouObjectType>> SplitList(List<YourObjectType> listToSplit) {
List<List<YouObjectType>> listOfLists = new List<List<YourObjectType>>();
List<YourObjectType> tmp = new List<YourObjectType>();
foreach(YourObjectType item in listToSplit) {
if (tmp.Count > 0
&& tmp[tmp.Count - 1] != item) {
// Compare you items here as you wish,
// I'm not sure what kind of objects
// and what kind of comparison you are going to use
listOfLists.Add(tmp);
tmp = new List<YourObjectType>();
}
tmp.Add(item);
}
if (tmp.Count > 0) {
listOfLists.Add(tmp);
}
return listOfLists;
}
Here is a simple way of doing that (no Linq)
List<Node> input = ...;
var output = new List<List<Node>>();
for (int end = 0; end < input.Count; )
{
int start = end;
while (++end < input.Count && input[end].markedForDoor == input[start].markedForDoor) { }
output.Add(input.GetRange(start, end - start));
}
Lookup Group Results by Contiguous keys on MSDN.
See how it applies to your case on Rextester.

displaying X number of items from a list

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.

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