I have looked through several articles but non seem to answer the problem that I am facing.
I guess the easiest way to explain is to break down my current code.
for (int i = 0; i < nodelist.Count; i++)
{
XmlNode node = nodelist[i];
XmlAttributeCollection attribute = node.Attributes;
count = 0;
cmdA.CommandText = "";
cmdsqlvalues = "";
cmdtgvalues = "";
for (int n = 0; n < attribute.Count; n++)
{
string tgfield = namefieldprojarray[i, n];
int index = -1;
index = Array.IndexOf(tgfieldprojarray, tgfield);
if (index != -1)
{
cmdsqlvalues = cmdsqlvalues +""+ sqlfieldprojarray[index]+",";
cmdtgvalues = cmdtgvalues + "" + valuefieldprojarray[i, n];
}
}
if (!valuefieldprojarray[i,0].Contains("$"))
{
cmdA.CommandText = "INSERT INTO proj_tasks ('" +cmdsqlvalues +"') VALUES ('" + cmdtgvalues + "')";
}
I have an XML document with several nodes that contain many attributes that I need to populate into a SQL database.
Some nodes have more or less attributes than others
Which is why I have included an IndexOf Array and added these values to a string array.
I am trying to use the sting array "cmdsqlvalues" as the table names, but when I try and insert into the SQL table the string array is appearing as one table column and trying to insert a huge column name.
It is important that I use string array because the number of nodes and the number of attributes for each node is large and is different for each node.
If anyone has come across a similar problem and has any input or advice then that would be highly appreciated.
Related
I want a 2D array generated from a CSV file with unknown number of rows/columns. The column count is fixed based on the header data. I need to be able to process it as a grid going both across rows and down columns hence needing array.
At the moment, I can split the data into rows, then split each row into components. I then add each row to a list. This all seems to work fine.
What I cant do is convert a list of string arrays into a 2d array.
It currently is failing on the line string[,] newCSV = csvFile.ToArray(); with error Cannot implicitly convert type 'string[][]' to 'string[ * , * ]' so I'm obviously not declaring something properly - I've just no idea what!
List<string[]> csvFile = new List<string[]>();
void Start()
{
// TODO: file picker
TextAsset sourceData = Resources.Load<TextAsset>("CSVData");
if (sourceData != null)
{
// Each piece of data in a CSV has a newline at the end
// Split the base data into an array each time the newline char is found
string[] data = sourceData.text.Split(new char[] {'\n'} );
for (int i = 0; i < data.Length; i ++)
{
string[] row = data[i].Split(new char[] {','} );
Debug.Log(row[0] + " " + row[1]);
csvFile.Add(row);
}
string[,] newCSV = csvFile.ToArray();
} else {
Debug.Log("Can't open source file");
}
Since your data is in the form of a table, I highly suggest using a DataTable instead of a 2d array like you're currently using to model/hold the data from your csv.
There's a ton of pre baked functionality that comes with this data structure that will make working with your data much easier.
If you take this route, you could then also use this which will copy CSV data into a DataTable using the structure of your CSV data to create the DataTable.
It's very easy to configure and use.
Just a small tip, you should always try to use data structures that best fit your task, whenever possible. Think of the data structures and algorithms you use as tools used to build a house, while you could certainly use a screw driver to pound in a nail, it's much easier and more efficient to use a hammer.
You can use this function to get 2d array.
static public string[,] SplitCsvGrid(string csvText)
{
string[] lines = csvText.Split("\n"[0]);
// finds the max width of row
int width = 0;
for (int i = 0; i < lines.Length; i++)
{
string[] row = SplitCsvLine(lines[i]);
width = Mathf.Max(width, row.Length);
}
// creates new 2D string grid to output to
string[,] outputGrid = new string[width + 1, lines.Length + 1];
for (int y = 0; y < lines.Length; y++)
{
string[] row = SplitCsvLine(lines[y]);
for (int x = 0; x < row.Length; x++)
{
outputGrid[x, y] = row[x];
// This line was to replace "" with " in my output.
// Include or edit it as you wish.
outputGrid[x, y] = outputGrid[x, y].Replace("\"\"", "\"");
}
}
return outputGrid;
}
I am planning to get an array of the averages of each column.
But my app crashes at sum[j] += int.Parse(csvArray[i,j]); due to a FormatException. I have tried using Convert.ToDouble and Double.Parse but it still throws that exception.
The increments in the for loop start at 1 because Row 0 and Column 0 of the CSV array are strings (names and timestamps). For the divisor or total count of the fields that have values per column, I only count the fields that are not BLANK, hence the IF statement. I think I need help at handling the exception.
Below is the my existing for the method of getting the averages.
public void getColumnAverages(string filePath)
{
int col = colCount(filePath);
int row = rowCount(filePath);
string[,] csvArray = csvToArray(filePath);
int[] count = new int[col];
int[] sum = new int[col];
double[] average = new double[col];
for (int i = 1; i < row; i++)
{
for (int j = 1; j < col; j++)
{
if (csvArray[i,j] != " ")
{
sum[j] += int.Parse(csvArray[i,j]);
count[j]++;
}
}
}
for (int i = 0; i < average.Length; i++)
{
average[i] = (sum[i] + 0.0) / count[i];
}
foreach(double d in average)
{
System.Diagnostics.Debug.Write(d);
}
}
}
I have uploaded the CSV file that I use when I test the prototype. It has BLANK values on some columns. Was my existing IF statement unable to handle that case?
There are also entries like this 1.324556-e09due to the number of decimals I think. I guess I have to trim it in the csvToArray(filePath) method or are there other efficient ways? Thanks a million!
So there are a few problems with your code. The main reason for your format exception is that after looking at your CSV file your numbers are surrounded by quotes. Now I can't see from your code exactly how you convert your CSV file to an array but I'm guessing that you don't clear these out - I didn't when I first ran with your CSV and experienced the exact same error.
I then ran into an error because some of the values in your CSV are decimal, so the datatype int can't be used. I'm assuming that you still want the averages of these columns so in my slightly revised verion of your method I change the arrays used to be of type double.
AS #musefan suggested, I have also changed the check for empty places to use the IsNullOrWhiteSpace method.
Finally when you output your results you receive a NaN for the first value in the averages column, this is because when you don't take into account that you never populate the first position of your arrays so as not to process the string values. I'm unsure how you'd best like to correct this behaviour as I'm not sure of the intended purpose - this might be okay - so I've not made any changes to this for the moment, pop a mention in the comments if you want help on how to sort this!
So here is the updated method:
public static void getColumnAverages(string filePath)
{
// Differs from the current implementation, reads a file in as text and
// splits by a defined delim into an array
var filePaths = #"C:\test.csv";
var csvArray = File.ReadLines(filePaths).Select(x => x.Split(',')).ToArray();
// Differs from the current implementation
var col = csvArray[0].Length;
var row = csvArray.Length;
// Update variables to use doubles
double[] count = new double[col];
double[] sum = new double[col];
double[] average = new double[col];
Console.WriteLine("Started");
for (int i = 1; i < row; i++)
{
for (int j = 1; j < col; j++)
{
// Remove the quotes from your array
var current = csvArray[i][j].Replace("\"", "");
// Added the Method IsNullOrWhiteSpace
if (!string.IsNullOrWhiteSpace(current))
{
// Parse as double not int to account for dec. values
sum[j] += double.Parse(current);
count[j]++;
}
}
}
for (int i = 0; i < average.Length; i++)
{
average[i] = (sum[i] + 0.0) / count[i];
}
foreach (double d in average)
{
System.Diagnostics.Debug.Write(d + "\n");
}
}
I'm adding values from a file to an array and then adding those values to a list box in a form. I have methods performing calculations and everything is working great, but I'd like to be able to use a loop and insert the year prior to the values I am inserting into the list box. Is there a way to use the .Add method and include a variable which will be changing in this? Something like populationListbox.Items.Add(i, value); if i is my loop counter? Code is below so I'd like first line in the list box to have the year I specify with my counter, followed by the population. Like this, "1950 - 151868". As of now it only displays the value 151868. Thanks!
const int SIZE = 41;
int[] pops = new int[SIZE];
int index = 0;
int greatestChange;
int leastChange;
int greatestYear;
int leastYear;
double averageChange;
StreamReader inputFile;
inputFile = File.OpenText("USPopulation.txt");
while (!inputFile.EndOfStream && index < pops.Length)
{
pops[index] = int.Parse(inputFile.ReadLine());
index++;
}
inputFile.Close();
foreach (int value in pops)
{
**populationListbox.Items.Add(value);**
}
greatestChange = greatestIncrease(pops) * 1000;
leastChange = leastIncrease(pops) * 1000;
averageChange = averageIncrease(pops) * 1000;
greatestYear = greatestIncreaseyear(pops);
leastYear = leastIncreaseyear(pops);
greatestIncreaselabel.Text = greatestChange.ToString("N0");
leastIncreaselabel.Text = leastChange.ToString("N0");
averageChangelabel.Text = averageChange.ToString("N0");
greatestIncreaseyearlabel.Text = greatestYear.ToString();
leastIncreaseyearlabel.Text = leastYear.ToString();
Like this?
int i = 1950;
foreach (int value in pops)
{
populationListbox.Items.Add(i.ToString() + " - " + value);
i++;
}
Your life will be a lot easier if you stop trying to program C# as if it were 1980s C and use the power of it's Framework:
var pops = File.ReadLines("USPopulation.txt").Select(int.Parse);
populationListbox.Items.AddRange(pops.Select((p,i) => $"{i} - {p}"));
I have a C# console window program and I am trying to sort "File3" (contains numbers) in ascending and output lines from 3 text files.
So the outcome looks something like this:
===========================================================================
field1.....................field2.....................field3
===========================================================================
[FILE1_LINE1]..............[FILE2_LINE1]..............[FILE3_LINE1]
[FILE1_LINE2]..............[FILE2_LINE2]..............[FILE3_LINE2]
[FILE1_LINE3]..............[FILE2_LINE3]..............[FILE3_LINE3]
and so on...
At the moment, it kinda works I think but it duplicates the first two lines it seems. Could someone give an example of better coding please?
Here is the code that I have atm:
string[] File1 = System.IO.File.ReadAllLines(#"FILE1.txt");
string[] File2 = System.IO.File.ReadAllLines(#"FILE2.txt");
string[] File3 = System.IO.File.ReadAllLines(#"FILE3.txt");
decimal[] File3_1 = new decimal[File3.Length];
for(int i=0; i<File3.Length; i++)
{
File3_1[i] = decimal.Parse(File3[i]);
}
decimal[] File3_2 = new decimal[File3.Length];
for(int i=0; i<File3.Length; i++)
{
File3_2[i] = decimal.Parse(File3[i]);
}
decimal number = 0;
for (double i = 0.00; i < File3_1.Length; i++)
{
for (int sort = 0; sort < File3_1.Length - 1; sort++)
{
if (File3_1[sort] > File3_1[sort + 1])
{
number = File3_1[sort + 1];
File3_1[sort + 1] = File3_1[sort];
File3_1[sort] = number;
}
}
}
if (SortChoice2 == 1)
{
for (int y = 0; y < File3_2.Length; y++)
{
for (int s = 0; s < File3_2.Length; s++)
{
if (File3_1[y] == File3_2[s])
{
Console.WriteLine(File1[s] + File2[s] + File3_1[y]);
}
}
}
}
Just for more info, most of this code was used for another program and worked but in my new program, this doesn't as I've said above - ("it repeats a couple of lines for some reason"). I'm kinda an amateur/ rookie at C# so I only get stuff like this to work with examples.
Thanks in advance :)
Ok, if I understand correctly, what you are trying to do is read the lines from 3 different files, each of them representing a different "field" in a table. You then want to sort this table based on the value of one of the field (in you code, this seems to be the field which values are contained in File3. Well, if I got that right, here's what I suggest you do:
// Read data from files
List<string> inputFileNames = new List<string> {"File1.txt", "File2.txt", "File3.txt"};
decimal[][] fieldValues = new decimal[inputFileNames.Count][];
for (int i = 0; i < inputFileNames.Count; i++)
{
string currentInputfileName = inputFileNames[i];
string[] currentInputFileLines = File.ReadAllLines(currentInputfileName);
fieldValues[i] = new decimal[currentInputFileLines.Length];
for (int j = 0; j < currentInputFileLines.Length; j++)
{
fieldValues[i][j] = decimal.Parse(currentInputFileLines[j]);
}
}
// Create table
DataTable table = new DataTable();
DataColumn field1Column = table.Columns.Add("field1", typeof (decimal));
DataColumn field2Column = table.Columns.Add("field2", typeof (decimal));
DataColumn field3Column = table.Columns.Add("field3", typeof (decimal));
for (int i = 0; i < fieldValues[0].Length; i++)
{
var newTableRow = table.NewRow();
newTableRow[field1Column.ColumnName] = fieldValues[0][i];
newTableRow[field2Column.ColumnName] = fieldValues[1][i];
newTableRow[field3Column.ColumnName] = fieldValues[2][i];
table.Rows.Add(newTableRow);
}
// Sorting
table.DefaultView.Sort = field1Column.ColumnName;
// Output
foreach (DataRow row in table.DefaultView.ToTable().Rows)
{
foreach (var item in row.ItemArray)
{
Console.Write(item + " ");
}
Console.WriteLine();
}
Now, I tried to keep the code above as LINQ free as I could, since you do not seem to be using it in your example, and therefore might not know about it. That being said, while there is a thousand way to do I/O in C#, LINQ would help you a lot in this instance (and in pretty much any other situation really), so I suggest you look it up if you don't know about it already.
Also, the DataTable option I proposed is just to provide a way for you to visualize and organize the data in a more efficient way. That being said, you are in no way obliged to use a DataTable: you could stay with a more direct approach and use more common data structures (such as lists, arrays or even dictionaries if you know what they are) to store the data, depending on your needs. It's just that with a DataTable, you don't, for example, need to do the sorting yourself, or deal with columns indexed only by integers. With time, you'll come to learn about the myriad of useful data structure and native functionalities the C# language offers you and how they can save you doing the work yourself in a lot of cases.
i want to populate an array element with 2 datarows at a time.
i am using javascript pausescroller and on every single array element i want to show 2 Rows in the scroller.
sample code is
Datatable tblNews;
for(int i = 0; i < tblNew.Rows.Count; i++)
{
array[i] = tblNews.Rows[i][""].ToString() + "" + tblNews.Rows[i + 1][""].ToString();
}
but problem is i am getting error that no row found at position 1;
Any solution guys
Yah, quite simply, when you're getting to the end of your tblNew.Rows.Count you're adding another one and that doesn't exist in your rows...
so a quick and dirty fix...
for(int i = 0; i < tblNew.Rows.Count-1; i++)
{
// do a quick check to make sure there is a row there to get data from
string addMe = i + 1 <= tblNews.Rows.Count-1 ? tblNews.Rows[i+1][""].ToString() : "";
array[i] = tblNews.Rows[i][""].ToString() + "" + addMe;
}