Updating a list within a list<class> - c#

Since having a list<list<>> is bad practice, i have created a class containing 2 lists:
public class TouchSet
{
public List<DateTime> timeList = new List<DateTime>(ammountOfXValues);
public List<int> touchList = new List<int>(ammountOfXValues);
}
Then i have a function that is used to initialize the entire thing so i can use it further down the road:
public void initializeTouchDataListObject()
{
touchSetList = new List<DataStructure.TouchSet>(DataStructure.maxButtonsActive);
List<int> tempTouchList = new List<int>();
List<DateTime> tempTimeList = new List<DateTime>();
for (int a = 0; a < DataStructure.maxButtonsActive; a++)
{
DataStructure.TouchSet tempTouchSet = new DataStructure.TouchSet();
tempTouchSet.timeList = tempTimeList;
tempTouchSet.touchList = tempTouchList;
touchSetList.Add(tempTouchSet);
}
}
This is the loop where i add values to the list:
for (int i = 0; i < DataStructure.maxButtonsActive; i++)
{
if(touchSetList[i].timeList.Count == DataStructure.ammountOfXValues)
{
//RemoveAt removes at the given index within a list
touchSetList[i].timeList.RemoveAt(0);
touchSetList[i].touchList.RemoveAt(0);
//add
touchSetList[i].timeList.Add(DateTime.Now);
touchSetList[i].touchList.Add(temp);
}
else if(touchSetList[i].timeList.Count < DataStructure.ammountOfXValues)
{
//add
touchSetList[i].timeList.Add(DateTime.Now);
touchSetList[i].touchList.Add(temp);
}
else
{
int overLength = touchSetList[i].timeList.Count - DataStructure.ammountOfXValues;
//remove
touchSetList[i].timeList.RemoveRange(0, overLength + 1);
touchSetList[i].touchList.RemoveRange(0, overLength + 1);
//add
touchSetList[i].timeList.Add(DateTime.Now);
touchSetList[i].touchList.Add(temp);
}
}
The issue I'm facing is, that within a single pass through the for loop , it adds temp to every touchList not just the touchList of touchSetList[i].
For example after adding temp to touchSetList[i].touchList every other touchList also contains temp, not just the one where the index i applies to the class within the list.
I'm not sure why the List is behaving this way, and why it adds the value to every list not just the one with the corresponding index. I was under the impression that you can use an index to access a single item within a list. Any pointers or advice is appreciated.

public void initializeTouchDataListObject()
{
touchSetList = new List<DataStructure.TouchSet>(DataStructure.maxButtonsActive);
for (int a = 0; a < DataStructure.maxButtonsActive; a++)
{
List<DateTime> tempTimeList = new List<DateTime>();
List<int> tempTouchList = new List<int>();
DataStructure.TouchSet tempTouchSet = new DataStructure.TouchSet();
tempTouchSet.timeList = tempTimeList;
tempTouchSet.touchList = tempTouchList;
touchSetList.Add(tempTouchSet);
}
}
You don't create a new tempTimeList and tempTouchList for every new tempTouchSet, so they all get passed pointers to THE SAME list.
Do the initialization for tempTimeList and tempTouchList within your loop and you get a new one for every tempTouchSet.

Actually I'd redesign the entire thing. What I read from your code is that you want to store the timestamp of a touch event together with some information about the touch event.
So I'd design a class that contains all that data:
public class TouchInfo
{
public DateTime touchTime;
public int touchEvent;
}
Then you can easily store one list of touch events, instead having to keep two lists in sync.
List<TouchInfo> touchEvents = new List<TouchInfo>();
public void initializeTouchDataListObject()
{
for (int a = 0; a < DataStructure.maxButtonsActive; a++)
{
touchEvents.add(new TouchInfo());
}
}

In your initializeTouchDataListObject() method, you create tempTouchList and tempTimeList. Then, for EVERY TouchSet, you add these lists as their timeList and touchList. The problem here is that the two created lists are passed by REFERENCE, meaning that every single TouchSet has a reference to the two exact same lists. They all share the same lists and thus lists are changed for every TouchSet in every iteration.

You have 3 conditions. Add(temp) is in all 3.
1) a < b
2) a = b
3) a > c
​

Related

C# - An object is deleted from an array that holds a copy of the original

I hold an array in the following structure
List[] pageStore = new List[2];
Each cell of the array will contain a list of Page objects.
I wrote a function that ran in a loop and in each iteration creates a new list of Page.
I keep the list created in the above List.
Before each iteration I delete the contents of pages and the deletion is also done on the array itself.
How can this be prevented so that the array will keep the records I saved?
my code :
List<Page>[] pageStore = new List<Page>[2];
public void LoadExcel(Dictionary<string,string[]> FilePaths){
List<Page> pages = new List<Page>();
int pageStoreIndex = 0;
foreach (KeyValuePair<string, string[]> entry in
FilePaths) {
pages.Clear();
for (int i = 0; i < entry.Value.Length; i++) {
if (i == 0)
pages = fileManager.ParseExcelToObjects(excelDataSet,
ProjectTypeSelected.Name,entry.Key.Equals(Enum.Enums.ConnectorSide.COMBINED.ToString()) ? false : true);
...
...
}
if (pages.Count > 0)
pageStore[pageStoreIndex++] = pages;
}
}
page.Clear() cleared pageStore also.
You need to create a copy of the list.
pageStore[pageStoreIndex++] = new List<Page>(pages);
Like most .Net objects, List<T> is a reference type. Your line:
pageStore[pageStoreIndex++] = pages;
is just storing a reference to the single pages instance. It's not copying the values across. Every array entry is pointing at the same list.
As other answers have said, you need to create a new list each time if you want to keep separate lists:
List<Page>[] pageStore = new List<Page>[2];
public void LoadExcel(Dictionary<string,string[]> FilePaths)
{
int pageStoreIndex = 0;
foreach (KeyValuePair<string, string[]> entry in FilePaths)
{
//create a new list for each loop iteration
var pages = new List<Page>();
for (int i = 0; i < entry.Value.Length; i++)
{
//ps the following lines don't make sense. You've created a new List above,
//but ParseExcelToObjects() ignores it and returns its own list.
//So either your new List<Page>() is pointless, or this call is different in the real code.
if (i == 0)
pages = fileManager.ParseExcelToObjects(excelDataSet, ProjectTypeSelected.Name,entry.Key.EqualsEnum.Enums.ConnectorSide.COMBINED.ToString()) ? false : true);
...
...
}
if (pages.Count > 0)
pageStore[pageStoreIndex++] = pages;
}
}
You've assigned the value in pageStore to be the pages object. You'll need to create a new object using List<T>'s copy constructor:
if (pages.Count > 0)
pageStore[pageStoreIndex++] = new List<Page>(pages);

Value inside a list gets changed on modification C#

Currently I have a class called Field:
public class Field
{
public int Id { get; set; }
}
var listOfListOfFields = new List<List<Field>>();
var listOfFields = new List<Field>(){ new Field {id = 1}}; // in reality, data comes here.
for (int i = 0; i <= 2; i++)
{
var copyFirstList = listOfFields.ToList(); // to avoid reference thing, I still get same value
for(int j =0; j < copyFirstList.Count; j++)
{
copyFirstList[j].Id = i;
}
listOfListOfFields.Add(copyFirstList);
}
The output in the listOfListOfFields contains 2 for all the lists in id. Please suggest.
Copying a list of references types gives you the same references to those reference types (nothing changed). For instance, if someone gave you a bucket of post-it-notes with phone numbers on them, and you tip them in to another bucket, you still have the same post-it-notes!
There are many ways to solve this problem. However, one way is to project using Select and recreating the objects
copyFirstList = listOfFields.Select(x => new Field() {Id = x.Id}).ToList():

Creating new class instance in a loop

I've just started learning about methods and classes, I would like to know if I can have something like,
CarsSold Day1 = new CarsSold();
in a for loop where it will create a new instance of a new day each time it runs. For example on the second time the loop runs I want it to create an instance like this,
CarsSold Day2 = new CarsSold();
I have tried to use an array but either it cant be done with arrays or I'm using the wrong syntax. Thanks in advance.
Full code
class Program
{
static void Main(string[] args)
{
int[] weekDay = new int[7];
int userInput;
int x;
for (x = 0; x < weekDay.Length; x++)
{
Console.Write("Enter the number of cars sold: ");
bool ifInt = int.TryParse(Console.ReadLine(), out userInput);
CarsSold Day[x] = new CarsSold(userInput);
}
}
}
The problem is how you're trying to define your array. The syntax is invalid, and you're doing it in the wrong place.
You should define the array before your loop, and then only assign values to the array within the loop.
static void Main(string[] args)
{
int userInput;
CarsSold[] days = new CarsSold[7]; // create an array with 7 items
int x;
for (x = 0; x < days.Length; x++)
{
Console.Write("Enter the number of cars sold: ");
bool ifInt = int.TryParse(Console.ReadLine(), out userInput);
days[x] = new CarsSold(userInput); // assign a value to the days array at position x.
}
}
Note also that arrays start from 0, not 1, so the first item is actually days[0], and the last is days[6] (for a 7-item array). I took the liberty of removing weekDays since it wasn't needed here, and replaced it in the loop with days.Length.
Arrays can have set amount of things in them, so if you declare an array like this
object[] objectArray = new object[10];
Then that array can hold only 10 objects. If you want to add anything to an array you have to chose an index to which that thing will be assigned to, for example:
objectArray[2] = "some value";
in Your case you could iterate through the array and add new object to each index like this
for (var i = 0; i < objectArray.Length; i++)
{
objectArray[i] = new YourObject();
}
If the amount of objects you want to store is unknown and can change then you should use collections, for example a List
List<object> listOfObjects = new List<object>();
Now if you want to add anything to that list you simply do
listOfObjects.Add(itemYouWantToAddToTheList);
You access lists the same way you would access arrays, so you can use indexes like
var someValue = listOfObjects[0];
As you probably noticed this list has a generic parameter <object>, it tells the list what type of data it can store, in my example its the object type so it can pretty much store anything, but you can set it to string or int or any other type like your own class types and then this list would store only those types of objects.
If you don't know the number of days, then:
IList<CarsSold> soldCarsList = new List<CarsSold>();
foreach(var day in Days)
{
soldCarsList.Add(new CarsSold());
}
If you know the number of days(e.g:7), then:
CarsSold[] soldCarsArray = new CarsSold[7];
for (int i = 0; i < days.Length; x++)
{
soldCarsArray[i] = new CarsSold();
}

C# Shuffle Cards Windows Forms

I am working on an assignment for school (Assignment Here).
I am currently trying to shuffle a deck of cards. I have used PlayingCards from Codeplex (sorry, could only have two links...) to create a collection of cards to create a deck. Please help, when I click the Shuffle button, nothing happens. You can see my progress here it's easier to see the entire code: Github
public void Shuffle()
{
PlayingCards.Deck theDeck = new PlayingCards.Deck();
random = new Random();
for (int i = 0; i < theDeck.Cards.Count; i++)
{
int second = random.Next(NUMBER_OF_CARDS);
PlayingCards.Card temp = theDeck.Cards[i];
theDeck.Cards[i] = theDeck.Cards[second];
theDeck.Cards[second] = temp;
}
}
You are creating a new instance of PlayingCards.Deck, shuffling it, and then throwing it away at the end of the shuffle.
PlayingCards.Deck theDeck = new PlayingCards.Deck();
You need to change the call to Shuffle to include PlayingCards.Deck as a parameter, so you should be doing this:
public void Shuffle(PlayingCards.Deck theDeck)
{
random = new Random();
for (int i = 0; i < theDeck.Cards.Count; i++)
{
int second = random.Next(NUMBER_OF_CARDS);
PlayingCards.Card
temp = theDeck.Cards[i];
theDeck.Cards[i] = theDeck.Cards[second];
theDeck.Cards[second] = temp;
}
}
You should also move the new Random() outside of this method as you may find that if you tried to create two shuffled decks immediately after one another that they'll have the same order because the seed Random uses is based on the system clock.
I had a look at the code you've got for adding the cards to the deck. You should use this code instead:
foreach (var face in Enum.GetValues(typeof(PlayingCards.CardSuits)).Cast<PlayingCards.CardSuits>())
{
foreach (var value in Enum.GetValues(typeof(PlayingCards.CardValues)).Cast<PlayingCards.CardValues>())
{
theDeck.Cards.Add(new PlayingCards.Card(face, value));
}
}

How to minus data length inside the index of a list, if the index is an array?

Well, first of all, I am not sure whether my title in this question delivered what I want to ask or not. I just do not sure how to describe my problem in one sentence, hopefully the title would not cause any misleading.
If I have a list. Inside the list contain 100 data : list<100>
If I put this list inside a 1 second timer tick and do like this:
myList.RemoveRange(0, 2);
This mean, every 1 second, the data length inside the list will be -2;
This mean, every 1 second, it will be <98> , <96> , <94> .... <0>
Now my problem is...I still have a list, but the list will contain an array: list<array[100]>
Now, what I want is, every 1 second, the data length inside the array inside the list will be -2. But I am not sure know how to do this...
what I want is, every 1 second <array[98]> , <array[96]> , <array[96]> ... <array[0]>
And so, if the list contain <array0[100] , array1[100], array2[100]>
if i put this list inside a loop, every 1 second, it should be
array0[98] , array0[96] ... array0[0]
array1[98] , array1[96] ... array1[0]
array2[98] , array2[96] ... array2[0]
Update:
List<int[]> myList = new List<int[]>();
object myLock = new object();
Random rand = new Random();
public Form1()
{
timer1second.Start();
}
private void SomeMethod()
{
int[] myData = new int [100]
for (int i = 0; i < 100; i++)
{
//generate some random number to store inside myData[]
myData[i] = rand.Next(1 , 10);
}
lock (myLock)
{
myList.Add(myData); //mean List[0] = myData[100]
}
}
private void timer1second_Tick(object sender, EventArgs e)
{
lock (myLock)
{
//do something here in myList to get the myData[100 - 2]
//so that every 1 second tick, the data length inside the MyData will be -2
}
}
Convert the Array item into a List.
Then remove the range from the List
Convert it back to an Array.
Insert it back into the List
Here is a sample:
int currentIndex = 0;
var myList = new List<int[]>();
var intArray = new int[100];
myList.Add(intArray);
// Convert to List.
var newIntArrayList = myList[currentIndex].ToList();
// Remove the ranges
// Index would be based on you logic
newIntArrayList.RemoveRange(0, 2);
//Replace the list with the new arry
myList[currentIndex] = newIntArrayList.ToArray();
Update : Array.Resize should also help.
int currentIndex = 0;
int arrayLength = 100;
var myList = new List<int[]>();
var intArray = new int[100];
myList.Add(intArray);
// Get the array
var array = myList[currentIndex];
// Resize
Array.Resize(ref array, arrayLength-2);
//Replace the list with the update array
myList[currentIndex] = array;
List<int> myList = new List<int>();
for (int i = 1; i < 101; i++)
{
myList.Add(i);
}
for (int i = 100; i > 0; i--)
{
System.Threading.Threading.Sleep(1000);
myList.RemoveAt(i);
i -= 1;
myList.RemoveAt(i);
}
Resizing lists and arrays is an expensive operation. Would you consider a custom data structure for your needs with convinient interface and optimized underlying structure? So every tick you will only increment and integer value representing offset:
class Data
{
const int Step = 2;
List<int[]> data;
List<int> cursors;
public Data()
{
data = new List<int[]>();
}
public void AddArray(int[] array)
{
data.Add(array);
cursors.Add(array.Length);
// or cursors.Add(0), depending on your needs
}
public void Tick()
{
for (int i = 0; i < cursors.Count; i++)
{
cursors[i] -= Step;
// or cursors[i] += Step, depending on your needs
}
}
public IEnumerable<int> GetValuesAtIndex(int index)
{
for (int i = 0, i < data[index].Length; i++)
{
if (i > cursors[index]) // or i < cursors[index]
{
yield return data[index][i];
}
}
}
}

Categories

Resources