C# Populate An Array with Values in a Loop - c#
I have a C# console application where an external text file is read. Each line of the file has values separated by spaces, such as:
1 -88 30.1
2 -89 30.1
So line one should be split into '1', '-88', and '30.1'.
What I need to do is to populate an array (or any other better object) so that it duplicate each line; the array should have 3 elements per row. I must be having a brain-lock to not figure it out today. Here's my code:
string line;
int[] intArray;
intArray = new int[3];
int i = 0;
//Read Input file
using (StreamReader file = new StreamReader("Score_4.dat"))
{
while ((line = file.ReadLine()) != null && line.Length > 10)
{
line.Trim();
string[] parts;
parts = line.Split(' ');
intArray[0][i] = parts[0];//error: cannot apply indexing
i++;
}
}
Down the road in my code, I intend to make some API calls to a server by constructing a Json object while looping through the array (or alternate object).
Any idea?
Thanks
If you only need the data to be transferred to JSON then you don't need to process the values of the data, just reformat it to JSON arrays.
As you don't know the number of lines in the input file, it is easier to use a List<>, whose capacity expands automatically, to hold the data rather than an array, whose size you would need to know in advance.
I took your sample data and repeated it a few times into a text file and used this program:
static void Main(string[] args)
{
string src = #"C:\temp\Score_4.dat";
List<string> dataFromFile = new List<string>();
using (var sr = new StreamReader(src))
{
while (!sr.EndOfStream)
{
string thisLine = sr.ReadLine();
string[] parts = thisLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 3)
{
string jsonArray = "[" + string.Join(",", parts) + "]";
dataFromFile.Add(jsonArray);
}
else
{
/* the line did not have three entries */
/* Maybe keep a count of the lines processed to give an error message to the user */
}
}
}
/* Do something with the data... */
int totalEntries = dataFromFile.Count();
int maxBatchSize = 50;
int nBatches = (int)Math.Ceiling((double)totalEntries / maxBatchSize);
for(int i=0;i<nBatches;i+=1)
{
string thisBatchJsonArray = "{\"myData\":[" + string.Join(",", dataFromFile.Skip(i * maxBatchSize).Take(maxBatchSize)) + "]}";
Console.WriteLine(thisBatchJsonArray);
}
Console.ReadLine();
}
to get this output:
{"myData":[[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1]]}
{"myData":[[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1],[1,-88,30.1],[2,-89,30.1]]}
It should be easy to adjust the format as required.
I would create a custom Item class and then populate a list, for easy access and sorting, with self contained items. something like:
public Class MyItem
{
public int first { get; set; }
public int second { get; set; }
public float third { get; set; }
public MyItem(int one, int two, float three)
{
this.first = one;
this.second = two;
this.third = three;
}
}
then you could do:
List<MyItem> mylist = new List<MyItem>();
and then in your loop:
using (StreamReader file = new StreamReader("Score_4.dat"))
{
while ((line = file.ReadLine()) != null && line.Length > 10)
{
line.Trim();
string[] parts;
parts = line.Split(' ');
MyItem item = new Item(Int32.Parse(parts[0]),Int32.Parse(parts[1]),Float.Parse(parts[2]));
mylist.Add(item);
i++;
}
}
As there are numbers like 30.1 so int is not suitable for this, and also it must not be a double[] but double[][]:
string[] lines = File.ReadAllLines("file.txt");
double[][] array = lines.Select(x => s.Split(' ').Select(a => double.Parse(a)).ToArray()).ToArray();
Issue is that int array is single dimensional.
My suggestion is that you can put a class with 3 properties and populate a list of class there. It's better to have class with same property names that you require to build JSON. So that you can easily serialize this class to JSON using some nugets like Newtonsoft and make api calls easily.
Your int array is a single dimensional array yet you're trying to index it like a multidemensional array. It should be something like this:
intArray[i] = parts[0]
(However you'll need to handle converting to int for parts that are fractional)
Alternatively, if you want to use a multidimensional array, you have to declare one.
int[][] intArray = new int[*whatever your expected number of records are*][3]
Arrays have a static size. Since you're reading from a file and may not know how many records there are until your file finishes reading, I recommend using something like a List of Tuples or a Dictionary depending on your needs.
A dictionary will allow you to have quick lookup of your records without iterating over them by using a key value pair, so if you wanted your records to match up with their line numbers, you could do something like this:
Dictionary<int, int[]> test = new Dictionary<int, int[]>();
int lineCount = 1;
while ((line = file.ReadLine()) != null && line.Length > 10)
{
int[] intArray = new int[3];
line.Trim();
string[] parts = line.Split(' ');
for (int i = 0; i < 3; i++)
{
intArray[i] = int.Parse(parts[i]);
}
test[lineCount] = intArray;
lineCount++;
}
This will let you access your values by line count like so:
test[3] = *third line of file*
Related
how to find average with strings c#
I need to set a variable as the average of 3 other variables, which are numbers but they are set as strings. How do I do this? I'm using c#, visual studio, windows forms. The variable i'm trying to set is called skiTime, the variables i'm using to get the average are called skiTime1, skiTime2 and skiTime3. basically i need the c# version of: skiTime = (skiTime1 + skiTime2 + skiTime3) / 3 The code where I start (declare? I don't know the word to use) the variables List<string> skiTime1 = new List<string>(); List<string> skiTime2 = new List<string>(); List<string> skiTime3 = new List<string>(); string skiTime The code where i set the value for the variables: using (StreamReader sr = new StreamReader("pupilSkiTimes.txt")) { string line = ""; while ((line = sr.ReadLine()) != null) { string[] components = line.Split("~".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); skiTime1.Add(components[2]); skiTime2.Add(components[3]); skiTime3.Add(components[4]); } sr.Close(); } I need to display skiTime1, skiTime2 and skiTime3 in a data grid view, so i think they need to be strings, if i'm not mistaken. skiTime will only be used in another calculation so maybe it can be turned into an int. I don't really know what i'm doing and only got this far because of tutorials, help. I can post the whole code if this question is too confusing or doesn't have enough information.
public string CalculateAverage(List<string> skiTime1, List<string> skiTime2, List<string> skiTime3) { List<string> allValues = new List<string>(); allValues.AddRange(skiTime1); allValues.AddRange(skiTime2); allValues.AddRange(skiTime3); float totalcount = 0; float average = 0; foreach (var value in allValues) { totalcount = totalcount + float.Parse(value); } average = totalcount / allValues.Count(); return average.ToString(); } Function for returning the average value Now call the function where u need like: string skiTime = CalculateAverage(skiTime1, skiTime2, skiTime3);
You need to parse the strings to decimals then calculate the average: List<decimal> avgTime = new List<decimal>(); for (var i = 0; i < skiTime1.Length; i++) { var avg = (decimal.Parse(skiTime1[i]) + decimal.Parse(skiTime2[i]) + decimal.Parse(skiTime3[i])) / 3; avgTime.Add(avg); }
split multiple whitespaces from text file to array
I have a text file and required to have all 7 elements including the empty ones to be parsed into an array for further processing. However, there are no unique delimiter to be make use of except for whitespaces and some of the data/value will come with whitespace. Example per "Data Sample" and some of the block will have null entry. How can i make this happen? Snippet of Data Actual Sample Data My end results would be some ting similar like below: Array[0]:123456789 Array[1]:HLTX Array[2]:5 Array[3]:BT5Q02 Array[4]:4SV Array[5]:D8041 Array[6]:LIANG LIN My code for the above function for now per below and it will omit the empty values. Which likely will missed out some of the data required. string[] splitlinecontent = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var OrderNum = splitlinecontent[0]; var OrderType = splitlinecontent[1]; int OrderQTY = int.Parse(splitlinecontent[2]); var OrderSINumInRpt = splitlinecontent[3]; var OrderHoldMod = splitlinecontent[5]; var SalesPerson = splitlinecontent[6];
I think bestpractice for these files is to use TextFieldParser from Microsoft.VisualBasic.FileIO; using (var parser = new TextFieldParser(fileName)) { parser.TextFieldType = FieldType.FixedWidth; parser.SetFieldWidths(3, 7, 10, 13, 8, 6, 1, 7, -1); while (!parser.EndOfData) { var fields = parser.ReadFields(); But I guess it isn't that hard to code the stuff yourself.
Based on the screenshot of your sample data, your columns have a fixed charsize of ten chars. You now can simply read the sample data line by line and split the lines by this fixed size. public static List<List<string>> GetRecords(string path, bool hasColHeader, int colLength, int colCount){ //Result will be stored in lists List<List<string>> result = new List<List<string>>(); //Get the sample file string[] records = File.ReadAllLines(path,Encoding.UTF8); //Go for each line through the data from sample file for(int n = 0; n<records.Length;n++){ //create new list for this line result.Add(new List<string>()); //here you can do something with headers. for simplification i do nothing with them and continue with next line. if(n==0 && hasColHeader){ continue; } //go for each column (colCount specifies the count of columns) for(int i = 0; i< colCount ;i++){ //if the length of the line is not devisible by colLength, you have to put some spaces to match the columns size //not the best way to do this but this is not the major point of this question if(records[n].Length % colLength != 0){ int charsToAdd = (colLength * colCount) - records[n].Length; string spaces = ""; for(int s = 0; s< charsToAdd; s++){ spaces += " "; } records[n] += spaces; } //add the result to the currently created list result[n].Add(records[n].Substring(i*colLength,colLength).Trim()); } } return result; } You can use this code like this: static void Main(string[] args) { List<List<String>> list = GetRecords(#"C:\temp\DataSample.txt",true, 10, 7); } The data in list looks like this: List[0]:List[0]:123456789 List[0]:List[1]:HLTX List[0]:List[2]:5 List[0]:List[3]:BT5Q02 List[0]:List[4]:4SV List[0]:List[5]:D8041 List[0]:List[6]:LIANG LIN List[1]:List[0]:3835443 List[1]:List[1]:HLTX List[1]:List[2]:1 ... Here you can optimize two things by youreself. Calculate the size of the columns by the chars between headers. The columnsize will alsways be the start of a columnheader and the start of the next columnheader. The charcount between this two points, will be the size of the column. Find a better way to get the last column! :D i dont think what i've done is good. There a better ways to do this.
How can I split a string to store contents in two different arrays in c#?
The string I want to split is an array of strings. the array contains strings like: G1,Active G2,Inactive G3,Inactive . . G24,Active Now I want to store the G's in an array, and Active or Inactive in a different array. So far I have tried this which has successfully store all the G's part but I have lost the other part. I used Split fucntion but did not work so I have tried this. int i = 0; for(i = 0; i <= grids.Length; i++) { string temp = grids[i]; temp = temp.Replace(",", " "); if (temp.Contains(' ')) { int index = temp.IndexOf(' '); grids[i] = temp.Substring(0, index); } //System.Console.WriteLine(temp); } Please help me how to achieve this goal. I am new to C#.
If I understand the problem correctly - we have an array of strings Eg: arrayOfStrings[24] = { "G1,Active", "G2,Inactive", "G3,Active", ... "G24,Active" } Now we want to split each item and store the g part in one array and the status into another. Working with arrays the solution is to - traverse the arrayOfStrings. Per each item in the arrayOfStrings we split it by ',' separator. The Split operation will return another array of two elements the g part and the status - which will be stored respectively into distinct arrays (gArray and statusArray) for later retrieval. Those arrays will have a 1-to-1 relation. Here is my implementation: static string[] LoadArray() { return new string[] { "G1,Active", "G2,Inactive", "G3,Active", "G4,Active", "G5,Active", "G6,Inactive", "G7,Active", "G8,Active", "G9,Active", "G10,Active", "G11,Inactive", "G12,Active", "G13,Active", "G14,Inactive", "G15,Active", "G16,Inactive", "G17,Active", "G18,Active", "G19,Inactive", "G20,Active", "G21,Inactive", "G22,Active", "G23,Inactive", "G24,Active" }; } static void Main(string[] args) { string[] myarrayOfStrings = LoadArray(); string[] gArray = new string[24]; string[] statusArray = new string[24]; int index = 0; foreach (var item in myarrayOfStrings) { var arraySplit = item.Split(','); gArray[index] = arraySplit[0]; statusArray[index] = arraySplit[1]; index++; } for (int i = 0; i < gArray.Length; i++) { Console.WriteLine("{0} has status : {1}", gArray[i] , statusArray[i]); } Console.ReadLine(); }
seems like you have a list of Gxx,Active my recomendation is first of all you split the string based on the space, which will give you the array previoulsy mentioned doing the next: string text = "G1,Active G2,Inactive G3,Inactive G24,Active"; string[] splitedGItems = text.Split(" "); So, now you have an array, and I strongly recommend you to use an object/Tuple/Dictionary depends of what suits you more in the entire scenario. for now i will use Dictionary as it seems to be key-value Dictionary<string, string> GxListActiveInactive = new Dictionary<string, string>(); foreach(var singleGItems in splitedGItems) { string[] definition = singleGItems.Split(","); GxListActiveInactive.Add(definition[0], definition[1]); } What im achiving in this code is create a collection which is key-value, now you have to search the G24 manually doing the next string G24Value = GxListActiveInactive.FirstOrDefault(a => a.Key == "G24").Value;
just do it : var splitedArray = YourStringArray.ToDictionary(x=>x.Split(',')[0],x=>x.Split(',')[1]); var gArray = splitedArray.Keys; var activeInactiveArray = splitedArray.Values; I hope it will be useful
You can divide the string using Split; the first part should be the G's, while the second part will be "Active" or "Inactive". int i; string[] temp, activity = new string[grids.Length]; for(i = 0; i <= grids.Length; i++) { temp = grids[i].Split(','); grids[i] = temp[0]; activity[i] = temp[1]; }
Reading each row from text file into an array of doubles or integer using C#
Suppose I have a text file with data like below, I want to read first row and store the elements in one array. Read the second row and store in second array and so on. I will be making some manipulations on the array later on. Can you help me to do this in C#? Input text file: 5,7,3,6,9,8,3,5,7 5,6,8,3,4,5 6,4,3,2,65,8,6,3,3,5,7,4 4,5,6,78,9,4,2,5,6 The Code I am trying out is: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace ReadFile { public partial class Form1 : Form { public Form1() { InitializeComponent(); } static void Main(string[] args) { TextReader tr = new StreamReader("Data.txt"); // write a line of text to the file string word = tr.ReadLine(); //now split this line into words string[] val = word.Split(new Char[] { ',' }); } } } If I use the above technique, I can get the first line in array val. Is there a way to loop it for all the rows?
File.ReadAllLines will help you read all lines from file as string array. String.Split will help you split line in pieces. Int.Parse will help you transform string to int (double has similar method).
Ok, since you are a beginner my suggestions on what to focalize your attention. First of all, are your consumer always needing all the lines or can it stop at some point? If so, use a yield strategy to return the results one by one. You can use a StreamReader to read line one by one in any case, and use double.TryParse(...) or int.TryParse() after splitting the string by the separator. Keep an eye to the fact that separator can change, so use it with some kind of configurability, and in the case of double, ensure your code works even in machines with a different decimal point configured. If you are sure your csv alwais uses '.' as a decimal point separator, specify double.TryParse("",System.Globalization.CultureInfo.InvariantCulture);
Something roughly like this would work: StreamReader reader = new (File.OpenRead(#"YourFile.txt")); List<string> LstIntegers = new List<string>(); while (!reader.EndOfStream) { var line = reader.ReadLine(); //values is actually a string array. var values = line.Split(','); //add the entire array fetched into string List LstIntegers.AddRange(values); } // important to close the reader. You can also use using statement for reader. It // will close the reader automatically when reading finishes. reader.Close(); // You can then further manipulate it like below, you can also use int.Parse or int.TryParse: foreach (var v in LstIntegers) { // use int.TryParse if there is a chance that a non-int is read. int someNum = Convert.ToInt32(v); }
Try this using System; using System.Collections.Generic; using System.Linq; using System.Xml; using System.IO; using System.Xml.Linq; using System.Diagnostics; namespace ConsoleApplication5 { class Program { static void Main(string[] args) { List<int[]> arrays = new List<int[]>(); int counter = 0; string line; // Read the file System.IO.StreamReader file = new System.IO.StreamReader("c:\\temp\\test.txt"); while ((line = file.ReadLine()) != null) { // split the line into a string array on , separator string[] splitLine = line.ToString().Split(','); // if our split isnt null and has a positive length if (splitLine != null && splitLine.Length > 0) { // create a lineArray the same size as our new string[] int[] lineArray = new int[splitLine.Length]; int posCounter = 0; foreach (string splitValue in splitLine) { // loop through each value in the split, try and convert // it into an int and push it into the array try { lineArray[posCounter] = Int32.Parse(splitValue); } catch { } posCounter++; } // if our lineArray has a positive length then at it to our // list of arrays for processing later. if (lineArray.Length > 0) { arrays.Add(lineArray); } } counter++; } file.Close(); // go through the List<int[]> and print to screen foreach (int[] row in arrays) { foreach (int rowCol in row) { Console.Write(rowCol + ","); } Console.WriteLine(); } // Suspend the screen. Console.ReadLine(); } } }
See this lines of code: List<List<int>> numbers = new List<List<int>>(); foreach (string line in File.ReadAllLines("")) { var list = new List<int>(); foreach (string s in line.Split(new[]{',', ' '}, StringSplitOptions.RemoveEmptyEntries)) { int i; if(int.TryParse(s, out i)) { list.Add(i); } } numbers.Add(list); } var specialNumber = numbers[3][4]; // gives line 3 number 4 var specialLine = numbers[2].ToArray(); // gives an array of numbers of line 2 description: I used this useful Generic: List: Represents a strongly typed list of objects that can be accessed by index and these useful Classes: File.ReadAllLines: Opens a text file, reads all lines of the file into a string array String.Split : Returns a string array that contains the substrings in this instance that are delimited by elements of a specified string or Unicode character array. Int.TryParse: Converts the string representation of a number to its 32-bit signed integer equivalent.
I have presented the following code in two sections, just to show you in steps. SECTION 1 This code is just to show that you just needed to loop through all lines and store string numbers from each line in a List. SECTION 1 static void Main(string[] args) { List<string[]> allLines = new List<string[]>(); TextReader tr = new StreamReader("Data.txt"); string word = tr.ReadLine(); // write a line of text to the file while ( word != null ) { //now split this line into words string[] vals = word.Split(new Char[] { ',' }); //Add this line into allLines allLines.Add(vals); //Now read the next line word = tr.ReadLine(); } } SECTION 2 This section will get you the results as int. static void Main(string[] args) { //A list of arrays of integers //A single array will have numbers from a single line List<int[]> allNumbers = new List<int[]>(); TextReader tr = new StreamReader("Data.txt"); string word = tr.ReadLine(); // write a line of text to the file while ( word != null ) { //now split this line into words string[] vals = word.Split(new Char[] { ',' }); int[] intVals = new int[vals.Length]; for ( int i = 0; i < vals.Length; i++) { Int32.TryParse(vals[i], out intVals[i]); } //Add this array of integers into allNumbers allNumbers.Add(intVals); //Now read the next line word = tr.ReadLine(); } } NOTE: I have not compiled or tested the code above.
I figured it out. Thanks all for your time! private void ReadFile() { var lines = File.ReadLines("Data.csv"); var numbers = new List<List<double>>(); var separators = new[] { ',', ' ' }; /*System.Threading.Tasks.*/ Parallel.ForEach(lines, line => { var list = new List<double>(); foreach (var s in line.Split(separators, StringSplitOptions.RemoveEmptyEntries)) { double i; if (double.TryParse(s, out i)) { list.Add(i); } } lock (numbers) { numbers.Add(list); } });
C# List to Array Problem
Still new to C# so be gentle :) I have some code which reads in a CSV file and stores the output in a List. I used a List instead of an Array as the number of entries in the CSV is undetermined. Once the List is created from the file I then want to pass it to a Shell sort method as this is the purpose of the program. To do this I first want to convert the list to an array of integers. I have tried the .ToArray method but it doesnt seem to be working for me. I get an exception Cannot Implicilty convert type String[][] to string[]. I know I am doing something stupid but cant seem to find out what... Any help would be appreciated. //Import DAT file and format it. public int[] ImportDat(string path) { List<string[]> loadedData = new List<string[]>(); loadedData.Clear(); try { using (StreamReader readCSV = new StreamReader(path)) { string line; string[] row; while ((line = readCSV.ReadLine()) != null) { row = line.Split(','); loadedData.Add(row); } } } catch { MessageBox.Show("Import Failed. Please check the file is in the same folder as the executable"); } string[] MyArray = loadedData.ToArray(); //temp Array to return a value int[] numbers = new int[5] { 1, 2, 3, 4, 5 }; return numbers; }
It seems like you really want a one dimensional list of numbers from your CSV file, but you are treating each row separately right now. If that is the case then use: loadedData.AddRange(row); instead of: loadedData.Add(row); and declare loadedData as List<string>. Now you still would have to do the conversion to int, since your method returns a list of int.Using LINQ you could do: List<int> results = loadedData.Select(s=> Convert.ToInt32(s)).ToList(); Your method also could be fully expressed with LINQ like this: public int[] ImportDat(string path) { List<int> result = File.ReadAllLines(path) .Select(line => line.Split(',')) .SelectMany(s => s) .Select( s=> Convert.ToInt32(s)) .ToList(); return result; }
Your variable loadedData is a List of string arrays. Calling .ToArray() on it will return a string[][] (2 dimensional array), not a string[].
Why don't you just use the list and convert the numbers right away? public int[] ImportDat(string path) { List<int> loadedData = new List<int>(); loadedData.Clear(); try { using (StreamReader readCSV = new StreamReader(path)) { string line; string[] row; while ((line = readCSV.ReadLine()) != null) { row = line.Split(','); foreach(var token in row) { loadedData.Add(Convert.ToInt32(token)); } } } } catch { MessageBox.Show("Import Failed. Please check the file is in the same folder as the executable"); } return loadedData.ToArray(); }
You are declaring loadedData as a list of string arrays. You should just do List<string> loadedData = new List<string>();
The problem is that each item in your List, is an array of strings. it's not a list of string. hench, you should make your "MyArray" a two dimensional array of strings. in other words, an array of arrays of strings. so in short: string[][] MyArray = loadedData.ToArray();
Perhaps you can modify this code to suit your needs? List<int> numbersList = new List<int>(); string input = "2,4,6,3"; string[] numbersStringArray = input.Split(','); foreach (var numberString in numbersStringArray) { numbersList.Add(Convert.ToInt32(numberString)); } int[] numbersArray = numbersList.ToArray<int>();