changing the value of certain elements of a list - c#

I am looping through a list and would like to add multiple occurrences, should I find them.
so far I have,
public struct optionsSort
{
public string name;
public string date;
public double strike;
public string callPut;
public double size;
public string isin;
}
List<List<optionsSort>> stocks = new List<List<optionsSort>>();
optionsSort tempStock1 = new optionsSort();
List<optionsSort> posCheckOptions = new List<optionsSort>();
then some code, then,
for(int k = 0; k<posCheckOptions.Count; k++)
{
for(int l = 0; l<posCheckOptions[l].Count; l++)
{
if(posCheckOptions[l+1] == null)
{
//finished the iteration
break;
}
else if
(posCheckOptions[k][l + 1].date == posCheckOptions[k][l].date
&& posCheckOptions[k][l + 1].strike == posCheckOptions[k][l].strike
&& posCheckOptions[k][l + 1].callPut == posCheckOptions[k][l].callPut)
{
posCheckOptions[k][l].size = posCheckOptions[k][l].size
+ posCheckOptions[k][l + 1].size;
}
}
}
Basicly, Im looking forward from the start of the list. asking the question, are certain elements of the list at i+1 the same as i, if so, add those elements to i and delete the entire row.
i get this error
"Error 1 Cannot modify the return value of 'System.Collections.Generic.List.this[int]' because it is not a variable C:\Users\WindowsFormsApplication1\WindowsFormsApplication1\ReadCSV.cs 890 25 WindowsFormsApplication1
"
Many Thanks for looking.

I believe your problem is that you are using a mutable struct. Mutable structs are evil.
The simplest solution is to change optionsSort to a class. That should fix the error message.
To explain the error message, when you call posCheckOptions[k][l], since optionsSort is a struct, it returns a copy of the value in the list. When you change size, it will update the copy, but not the one in the list. The copy would then be discarded. The compiler recognizes this and stops you.
I recommend you read up on the differences between reference types and value types.

Related

C# - Concatenate inside a loop

Is it possible to concatenate inside a C# loop? Below is my sample code:
for (int i = 0; i <= metricCount; i++)
{
if (m.metrictNumber == i)
{
aggrgt.Add(new PlainBrgDataSummaryChartAggrgt
{
scoreWk6 = scoresPerDuration.scoresPerDuration.scoreWk6.metricScore1,
scoreWk5 = scoresPerDuration.scoresPerDuration.scoreWk5.metricScore1,
scoreWk4 = scoresPerDuration.scoresPerDuration.scoreWk4.metricScore1,
scoreWk3 = scoresPerDuration.scoresPerDuration.scoreWk3.metricScore1,
scoreWk2 = scoresPerDuration.scoresPerDuration.scoreWk2.metricScore1,
scoreWk1 = scoresPerDuration.scoresPerDuration.scoreWk1.metricScore1
});
}
}
What I want is to concatenate metricScore1.
Here's what I tried:
scoreWk6 = scoresPerDuration.scoresPerDuration.scoreWk6.metricScore + i,
Is that possible?
You cannot. If you see numbers in variable names, it's probably wrong. Numbering your variables means you should have used a container type. Either an array or a list or anything else that supports going through it with a loop index or foreach.
So the answer is no. No, you cannot. You should change the types holding your data.

Example of Indexer

I'm learning about Indexers and stumble across the explanation and example of the tutorial I'm reading.
It says:
"An indexer allows an object to be indexed such as an array. When you define an indexer for a class, this class behaves similar to a virtual array. You can then access the instance of this class using the array access operator ([ ])"
What I understand with this paragraph is that you can access an instance of that class using the array access operatos.
But what I really dont understand of this explanation is the following:
"Declaration of behavior of an indexer is to some extent similar to a property. similar to the properties, you use get and set accessors for defining an indexer. However, properties return or set a specific data member, whereas indexers returns or sets a particular value from the object instance. In other words, it breaks the instance data into smaller parts and indexes each part, gets or sets each part".
I dont get the "It breaks the instance data into smaller parts and indexes each part"
After this it gives an example of Indexer:
using System;
namespace IndexerApplication
{
class IndexedNames
{
private string[] namelist = new string[size];
static public int size = 10;
public IndexedNames()
{
for (int i = 0; i < size; i++)
namelist[i] = "N. A.";
}
public string this[int index]
{
get
{
string tmp;
if( index >= 0 && index <= size-1 )
{
tmp = namelist[index];
}
else
{
tmp = "";
}
return ( tmp );
}
set
{
if( index >= 0 && index <= size-1 )
{
namelist[index] = value;
}
}
}
static void Main(string[] args)
{
IndexedNames names = new IndexedNames();
names[0] = "Zara";
names[1] = "Riz";
names[2] = "Nuha";
names[3] = "Asif";
names[4] = "Davinder";
names[5] = "Sunil";
names[6] = "Rubic";
for ( int i = 0; i < IndexedNames.size; i++ )
{
Console.WriteLine(names[i]);
}
Console.ReadKey();
}
}
}
Before that paragraph I thought Indexers where a form to index and instance of that class as an array, but that "smaller parts" I really dont understand.
It's really just giving an example of the use of an indexer. Returning an element from the array is, in a way, returning part of the array.
But it needn't be an array. For example, String has an indexer which returns the character at that position, e.g. "test"[0] returns the character in position zero, which is 't'.
Other objects may have other indexers which do other things. For example a DataTable DataRowCollection has an indexer which returns rows by number, and which has an indexer which returns columns by name:
myDataTable.Rows[12]["ID"].Value

c# Confusion over what type of array and usage

I am new to c# and am trying to build an array of arrays of items. I have looked at 2d arrays and jagged arrays and simply can't work out what i'm supposed to be using and can not get it to work. It's not so much building the array it's then looping through it to interrogate the array elements. I'm working within an existing library which is where all the variables come from, most of the other supporting code I've left out as it's not relevant. Once a instance is found i'm then trying to update a field from 0 to 1. Many thanks for any help in advance.
//Declare array
private double[,] myOpenTrades;
private void mymethod (double score, double RSIComboScore, int type, int line)
{
myOpenTrades[line,0] = type;
myOpenTrades[line,1] = CurrentBar;
myOpenTrades[line,2] = Close[0];
myOpenTrades[line,3] = rewardClose;
myOpenTrades[line,4] = riskClose;
myOpenTrades[line,5] = score;
myOpenTrades[line,6] = RSIComboScore;
myOpenTrades[line,7] = this.getSMATrend();
myOpenTrades[line,8] = Math.Round(NSRSICS(5, 15, 60, 240).Rsi200AVGPlot[0]);
myOpenTrades[line,9] = myReward;
myOpenTrades[line,10] = myRisk;
myOpenTrades[line,11] = 0;
}
protected override void OnMyChange()
{
foreach(double[] row in myOpenTrades)
{
if(Close[0] >= row[3] && row[11]==0)
{
Print("WIN:"+row[10]);
row[11]=1;
}
else if(Close[0] >= row[4] && row[11]==0)
{
Print("LOSE:"+row[9]);
row[11]=1;
}
}
{
I don't know why this is being downvoted, it seems like a legitimate question from a new user who made some effort.
To answer your question, an array of arrays is not the best choice, because from a logical organization perspective you don't have a "grid" (i.e. 2D array) of the same item, you have multiple items as one record, and an array of records. Not to mention that you appear to be trying to mix and match types; your array is declared as double but the first record type is an integer.
I would recommend using a class as follows:
class OpenTrades
{
public int Type;
public Bar CurrentBar;
public double Score;
// etc...
}
(This is assume that CurrentBar's type is Bar; you'll have to substitute Bar with whatever that type actually is.)
Then you would instantiate an array of your class like this:
OpenTrades[] myOpenTrades = new OpenTrades[11]; // This will create an array of 11 elements, indices 0 to 10
Now in your mymethod function you can assign values to each of your members.
myOpenTrades[line].Type = type;
myOpenTrades[line].Bar = CurrentBar;
myOpenTrades[line].Score = score;
// etc ...

going through a list with a for loop

Okay, i have a list and where i have structs stored, and i need to go through them from the last to the first, to check if one of the variables in the struct is 1. the code look like this:
for(int i = (checkpoints.Count - 1); i == 0; i--)
{
if(checkpoints[i].active == 1)
{
playerPositionX = checkpoints[i].xPosition;
playerPositionY = checkpoints[i].yPosition;
camPositionX = checkpoints[i].xPosition;
break;
}
}
this is the struct that i use:
private struct checkpoint
{
public int xPosition;
public int yPosition;
public int active;
}
what i need to do is to check if the variable active is == 1 in the struct that i have stored in the list. i have around 3-8 structs stored in the list. I need to start the check from the last struct in the list and work my way to the first.
when i try to debug the program it looks like it's not going from the last, but it starts at i=0.
please leave a comment if you have a fix, or if you need more information.
You can also use LastOrDefault() function. But, here can be one problem, because we are searching for Struct.
If nothing found?
LastOrDefault() will return default(checkpoint) if nothing found. The default value of a struct is the struct with all its values in turn default initialized. So, we must cast them to nullable using .Cast<checkpoint?>.
var activeCheckPoint = checkpoints
.Where(x => x.active == 1)
.Cast<checkpoint?>()
.LastOrDefault();
Or we must do the second check afterward that the returned object's active value is 1.
var activeCheckPoint = checkpoints.LastOrDefault(x => x.active == 1);
if(actactiveCheckPoint.active == 1)
{
// Then it is Ok
}
else
{
// Nothins was found
}
But, if you want to use for loop, then you must change i == 0 to i >= 0.
Your mistake was that you said to go though the loop if i was equal to 0, when it wasn't. You want the loop to loop until i is greater or equal to zero.
for(int i = (checkpoints.Count - 1); i >= 0; i--) // your mistake was here
{
if(checkpoints[i].active == 1)
{
playerPositionX = checkpoints[i].xPosition;
playerPositionY = checkpoints[i].yPosition;
camPositionX = checkpoints[i].xPosition;
break;
}
}

Designing a simple console trivia application

We have been tasked with designing a C# trivia application as a File I/O exercise. So far, I've got a good start, but the presentation step is kind of stumping me.
I'm starting with a delimited file featuring the following data:
Question;CorrectAnswerA;AnswerB;AnswerC;AnswerD;AnswerExplanation
e.g.,
What color is the sky?;Blue;White;Green;Yellow;The sky is blue.
The game will display the question and the four answers from which the user can select.
What Color is the Sky?
A. Blue
B. White
C. Green
D. Yellow
Select A, B, C, or D:
Unfortunately, for ease of populating the dataset, A is always the correct answer. I want to randomize the order in which the four answers display, but the program still needs to know which was the correct answer. I also need to have a user input of A, B, C, or D tie back to a specific instance of an answer to compare the selectedAnswerString to the correctAnswerString.
I've been playing with an array of the four answers which are randomly populated, but I can't wrap my head around how to flag something as correct based on the user's choice; my logic to do or assign that always seems to fall out of scope or duplicate across all four records in the array.
Other students I've talked to said they created their datasets with the answers pre-scrambled (so they can just print them in the order read) with a FIFTH answer field for the correct answer. While definitely an EASY way to make it happen, I don't think it's as elegant as my strategy.
Should I just change the input dataset? does anyone have any ideas on a good way to pursue my idea for the randomization?
Create a class called Question with properties: int Id, string QuestionText, List<string> Answers, string CorrectAnswer
Or, as step forward, also create class Answer with Id and Value and reference to it.
public class Question
{
public int Id;
public string QuestionText;
public List<Answer> Answers;
public Answer CorrectAnswer;
}
public class Answer
{
public int Id;
public string Value;
}
Afterwards populate this structure and randomize when printing
Keep track of the correct answer using a separate variable. Then use Fisher-Yates to shuffle your array:
Random random = new Random();
void Shuffle(string[] answers) {
for (int i = 0; i < answers.Length - 1; i++) {
int j = random.Next(i, answers.Length);
string temp = answers[j];
answers[j] = answers[i];
answers[i] = temp;
}
}
After the user responds, just compare their selection with the correct answer you've saved.
Try defining your data structure for a question in this way:
public class Question
{
public string Question;
public string[] Answers;
public int CorrectAnswer;
public string CorrectAnswerExplanation
}
This way you can scramble the strings in the array Answers, while still keeping track of the index of the correct answer in CorrectAnswer.
Alternatively if you can't use a separate class to model the question (this is a homework question so maybe you have not learned this yet), you can use a predetermined position in the array (the 1st or the 5th element) to hold the index of the correct answer. So your array for answers would look like:
"Blue", "White", "Green", "Yellow", "0"
Step 1: Define a data structure. Others have already given you a structure so use that.
Step 2: Populate your data structure. You could System.IO.File.ReadLines and parse each line - I assume you have this bit handled already.
Step 3: Randomize the order of your answers. For this, assuming you have your structure:
public static void RandomiseAnswers(IEnumerable<Question> questions)
{
var rand = new Random((int)DateTime.Now.Ticks);
foreach (var question in questions)
{
question.Answers = question.Answers.OrderBy(x => rand.Next()).ToArray();
}
}
Step 4: Recieve gold star from teacher for your outstanding work
Personally I'd put a boolean in the Answer class defaulting to false. This way when the answer is selected you can read whether it's correct or not.
public class AskQuestion
{
public int Id;
public string Question;
public string Explanation;
public List<Answer> Answers = new List<Answer>();
}
public class Answer
{
public bool Correct = false;
public string Value;
}
now when you randomize the list the correct answer is automatically identified
One way to use these classes would be like this:
static void Main(string[] args)
{
StreamReader sr = new StreamReader("text.txt");
List<AskQuestion> Questions = new List<AskQuestion>();
Random rnd = new Random(DateTime.Now.Millisecond);
//Loop through the file building a list of questions
while(!sr.EndOfStream)
{
AskQuestion NewQuestion = new AskQuestion();
string[] input = sr.ReadLine().Split(';');
NewQuestion.Question = input[0];
NewQuestion.Explanation = input[5];
for(int i = 1; i < 5; i++)
{
Answer NewAnswer = new Answer();
NewAnswer.Value = input[i];
NewQuestion.Answers.Add(NewAnswer);
}
//The first question is always correct so set its boolean value to true;
NewQuestion.Answers[0].Correct = true;
//Now ranmdomize the order of the answers
NewQuestion.Answers = NewQuestion.Answers.OrderBy(x => rnd.Next()).ToList();
Questions.Add(NewQuestion);
}
//Generate menu and get response for each question
foreach(AskQuestion q in Questions)
{
Console.WriteLine(q.Question + ":\n\tA - " + q.Answers[0].Value + "\n\tB - " + q.Answers[1].Value + "\n\tC - " + q.Answers[2].Value + "\n\tD - " + q.Answers[3].Value + "\n");
char input = '0';
while(input < 'A' || input > 'D')
{
input = char.ToUpper(Console.ReadKey().KeyChar);
if(input >= 'A' && input <= 'D')
{
//Use the boolean value in the answer to test for correctness.
if(q.Answers[input - 'A'].Correct)
{
Console.WriteLine("\nCorrect\n");
}
else
Console.WriteLine("\nWrong\n");
Console.WriteLine(q.Explanation);
}
}
}
Console.ReadLine();
}

Categories