How to import from a dynamic array - c#

My program has to place objects on a map, i have to get the informations about the objects from a text file but my problem is that there is no limit in objects so when i write my code i don't know if someone wants to place 1 or 10 or 5 objects. Every object has a separate line where you can give the parameters for example x,y coordinates on the map to place etc etc.
I figured out that i will ask the user to write in a line before the objects the number of objects he wants to add.Here is my example :
txt file:
200<----not important here
10000<----not important here
5<---number of objects
2,5/60-60<--object
4,5/70-70<--object
5,5/80-80<--object
1,1/30-30<--object
10,10/100-100<--object
10,1/5<----not important here
height,weight/x-y
And vs throws out of range exception. Hope u understood my english and my problem
int numberofObjects = int.Parse(data[2]);
Targets[] TargetsGet = new Target[numberofObjects];
int j = 0;
for (int i = 4; i <= numberofObjects+3; i++)
{
targets[j] = new Target(int.Parse(data[i].Split(',')[0]), int.Parse(data[i].Split('/')[0].Split(',')[1]), new Coordinate(int.Parse(data[i].Split('/')[1].Split('-')[0]),int.Parse( data[i].Split('-')[1])));
j++;
}
return TargetsGet;
}

First of all, your solution works.
If you don't want to ask the user to specify the number of objects, you can use a list instead of an array and use a separator at the end of the object list. For example:
List<Targets> TargetsGet = new List<Target>();
int j = 0;
while(data[j]!="separator")
{
targets.Add(new Target(int.Parse(data[j].Split(',')[0]), int.Parse(data[j].Split('/')[0].Split(',')[1]), new Coordinate(int.Parse(data[j].Split('/')[1].Split('-')[0]),int.Parse( data[j].Split('-')[1])));
j++;
}
return TargetsGet.ToArray();
}
The file should be modified so the string "separator" will be after the object list:, for example:
200<----not important here
10000<----not important here
2,5/60-60<--object
4,5/70-70<--object
5,5/80-80<--object
1,1/30-30<--object
10,10/100-100<--object
separator
10,1/5<----not important here
height,weight/x-y

Related

C# Pull items from array based on string

Not sure if this is the best way to do this but I've created a 2D array from values in an excel file that i want to use as variables within my application that control where to look for things like file paths and files.
The array is built and all data from the file is contained within it:
for (int i = 0; i <= bindingSourceConfig.Count - 1; i++) // for each row in the binding source data
{
for (int j = 0; j <= 2 - 1; j++) // for each column, only need one and 2
{
System_Var_Array[i, j] = (bindingSourceConfig.DataSource as DataTable).Rows[i][j].ToString();
}
}
Now i want to be able to look in the array for my variable say "Project_Directory" and have it return "C:\Users\User\Dropbox\default\master\support"
Is this even possible?
EDIT 1:
Purpose of doing it this way is to make an easily customizable/configurable multi project environment where by anyone can simply edit the paths in the excel file and import that file into the application.
I can not in my incompetence see a way of setting these 'variables' at a class level without first extracting the 'variable' and the 'value' from the excel data.
Is there a simple way of looking up the 'variable' in bindingSource?
EDIT 2:
debugger image
var name = "Project_Directory";
string value = null;
for (int i = 0; i<System_Var_Array.GetLength(0); i++) {
if (System_Var_Array[i,0]==name) {
value = System_Var_Array[i,1];
break;
}
}
After the loop stop, value will contain the data you need, assuming it exists (otherwise it will be null. A far simpler approach will be using Dictionary<string,string>, if you generate it with
var systemVars = new Dictionary<string,string>();
var dt = bindingSourceConfig.DataSource as DataTable;
for (int i = 0; i < bindingSourceConfig.Count; i++) // for each row in the binding source data
{
systemVars[dt.Rows[i][0].ToString()] = dt.Rows[i][1].ToString();
}
then to get the value for "Project_Directory", simply call
var value = systemVars["Project_Directory"];
You should use an appsettings file for this instead, it's the dotnet standard solution for this sort of thing. Please see https://learn.microsoft.com/en-us/dotnet/core/extensions/configuration.

C# Array of List Index out of bounds

I've made a program that extracts some info from a file , do some operations with it and store it back on a list.
Following this link:
Are 2 dimensional Lists possible in c#?
I've been able to create a class with a list who would suit my needs. But after some debugging i've found that i was overwriting the list on each loop iteration.
Then i decided to make an array of lists - followed this link:
How to create an array of List<int> in C#?
Created an array of lists, initialized it and added elements. But when it needs to move to the next list position , it throws the out of boundaries exception.
I've tried a few things (readed about race condition) but none of 'em worked.
The problem will happen only when i open more than one file with my code ; otherwise it works perfectly.
Exception is thrown at xmldata , in the last iteration of the current file.
Ex: Selected two files, each one will add five elements. In the last element of the first file the exception will be thrown and there's data in the last element's position to be added.
Additional information: Index was outside the bounds of the array. (Exception thrown).
Any help will be appreciated. Thanks a lot.
Code:
List<xmldata>[] finalcontent = new List<xmldata>[9999];
finalcontent[listpos] = new List<xmldata>();//Initializing a list for each filename
foreach (Match m in matches)
{
Double[] numbers;
string aux;
aux = m.Groups[1].ToString();
aux = Regex.Replace(aux, #"\s+", "|");
string[] numbers_str = aux.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
numbers = new Double[numbers_str.Length];
for (int j = 0; j < numbers.Length; j++)
{
numbers[j] = Double.Parse(numbers_str[j], CultureInfo.InvariantCulture);
//Converts each number on the string to a Double number, store it in a position
//in the Double array
numbers[j] = numbers[j] / 100; //Needed calculus
numbers[j] = Math.Round(numbers[j], 3); //Storing numbers rounded
}
string values = String.Join(" ", numbers.Select(f => f.ToString()));
if (i <= colors_str.Length)
{
finalcontent[listpos].Add(new xmldata//The exception is thrown right here
{
colorname = colors_str[i],
colorvalues = values,
});//Closing list add declaration
}//Closing if
i++;
}//Closing foreach loop
Link to the file: https://drive.google.com/file/d/0BwU9_GrFRYrTT0ZTS2dRMUhIWms/view?usp=sharing
Arrays are fixed size, but Lists automatically resize as new items are added.
So instead, and since you're using Lists anyway, why not use a list of lists?
List<List<int>> ListOfListsOfInt = new List<List<int>>();
Then, if you really absolutely must have an array, then you can get one like this:
ListOfListsOfString.ToArray();
// Convert non-ascii characters to .
for (int jx = 0; jx < cnt; ++jx)
if (line[jx] < 0x20 || line[jx] > 0x7f) line[jx] = (byte)'.';
This is a big example, but check this one. You increase 'jx' before entering the statement, possibly exceeding the boundary of cnt?
Try changing the following:
if (i <= colors_str.Length)
to
if (i < colors_str.Length).
In fact I'm convinced that this is the problem.
This is because refereces begin at 0 and the last reference is length - 1, not length.
When using a list - it is better to use native functions for it.
List<xmldata>[] finalcontent = new List<xmldata>();
......
finalcontent[listpos] = new List<xmldata>(); insted of var _tmpVariable = new List<xmldata>();//Initializing a list for each filename
......
_tmpVariable.Add(new xmldata
{
colorname = colors_str[i],
colorvalues = values,
});//Closing list add declaration
fs.Close();//closing current file
listpos++;//Increment list position counter
finalcontent.Add(_tmpVariable); // add list into list
As there is no exception details it is hard to get where the exception is thrown.
It could be a list issue, a string issue or other (even file reading issue as well),
So please update this with current exception details.

How can I make a 2D array from this one-line, comma delimited file?

I am trying to figure out how to turn the following, one-line CSV file into a 30x30 2D array.
http://pastebin.com/8NP7s7N0
I've tried looking it up myself, but I just can't seem to wrap my brain around the concept of multidimensional arrays, and I don't know how to turn a one-line file like this into an array of a specified size.
I want to be able to make an array that would look like this when printed:
0,0 = 2
0,1 = 2
All the way to 30,30.
Most of the numbers in the CSV are indeed 2's, but some are 1s. The difference is very important though. I am trying to make collision detection for a game, and this CSV file is the map. All I need left is how to create this array - leave the rest to me. :)
Thank you very much to all, have a nice day.
This should be a complete example using a 5 x 5 grid. I've tried it and seems to work as expected:
namespace ConsoleApplication1
{
using System;
class Program
{
const int MapRows = 5;
const int MapColumns = 5;
static void Main(string[] args)
{
// Create map and the raw data (from file)
var map = new int[MapRows, MapColumns];
string rawMapData = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25";
string[] splitData = rawMapData.Split(',');
int index = 0;
// Loop through data
for (int row = 0; row < MapRows; row++)
{
for (int column = 0; column < MapColumns; column++)
{
// Store in map and show some debug
map[row, column] = int.Parse(splitData[index++]);
Console.WriteLine(string.Format("{0},{1} = {2}", row, column, map[row, column]));
}
}
// Wait for user to read
Console.ReadKey();
}
}
}
Assuming your file is 900 elements first you need to read it in..
something along the lines of
line = myStreamReader.readLine().Split(',').. then in John U's example, value would be the next index in this array called line
I'll let you work out whats missing from my example :P
well, first you need to get the numbers...
var numbers = Read_File_As_String().Split(new char[',']).Select(n => int.Parse(n)).ToList();
then, you need to build your array
const int ROWS = 30;
const int COLS = 30;
var result = new int[ROWS, COLS];
for (int row = 0; row < ROWS; row++)
for (int col = 0; col < COLS; col++)
result[row, col] = numbers[(row * COLS) + col];
for(row=0;row<30;row++)
{
for(col=0;col<30;col++)
{
array[row][col] = value;
}
}
Value would need to be moved along to point to the next thing each time, but I'm sure you can figure that out.
Edited to add: If it's a map it might be easier to store it as an array in the first place.
Since you asked about the concept of multi-dimensional arrays, here are some useful ways of thinking about arrays. Please note these are analogies, meant to help you visualize them.
Think of a 1D array as a list of items (not in the programming sense of list!).
Think of a 2D array as a table (again, not in the programming sense!). In a table (like a spreadsheet) you have rows and columns, and each dimension in your array accesses one of these.
For higher dimensional arrays, it may help to think geometrically. For instance, you can think of 3D arrays as 3-dimensional points in space, and 4D arrays as 4-dimensional points in space-time.
So if you have a single CSV file, start off by conceptualizing how this would be re-structured as a table. Once you have that, you have a pretty straight-forward mapping to the array.

Programatically reference ascending variable names (var1, var2, ... )

I'm currently coding a project that can take up to 200 entries of a specific product, as determined by user input. Basically, my GUI loads, and I use jQuery to dynamically build the entries whenever there is a change to the amount field. When using jQuery, I simply give each of them ids in the form of variable1, variable2, ...., variableX (where X is the amount of entries indicated). Small snippet of code to clarify:
for(var i = 1;i <= amount_selected; i++) {
$('table_name tr:last').after('<tr><td><input type="text" id="variable' + i + '"></td></tr>');
}
Now when I try to move to the back end, I'm trying to reference these variable names by putting them in a list. I went ahead and put them in a list of HtmlInputText, to call the Variable names from the list itself. (This would save having to call all (up to 200) methods manually, which is really not an option).
So what I did (in C#) was:
List<HtmlInputText> listvar = new List<HtmlInputText>();
for(int i = 1; i <= amount_selected; i++) {
string j = "variable" + Convert.ToString(i);
HtmlInputText x = j;
listvar.Add((x));
samplemethod(listvar[i]);
}
But it's not working at all. Does anyone have any ideas as to how this would be done, without doing so manually? I know my logic might be completely off, but hopefully this illustrates at least what I'm attempting to do.
I'm assuming these inputs are in a form? If you're submitting then you can access the text boxes from the Request object:
List<string> results = new List<string>();
for (int i = 1; i <= amount_selected; i++)
{
string s = String.Format("{0}", Request.Form["variable" + Convert.ToString(i)]);
results.Add(s);
}
you could do $("#variable" + Convert.ToString(i)).val()

Create text files of every combination of specific lines within a base text file

Ok, so hopefully I can explain this in enough detail for somebody to be able to help me.. I am writing a program in C# that is supposed to take a text file and replace specific text, which happen to be names of files, and print a new text file for every single combination of the given filenames. The specific places to change the text of filenames have their own set of possible filenames, listed as an array described below. The program should run regardless of how many filenames are available for each location as well as how many total locations for the filenames. If you really wanted to make it awesome, it can be slightly optimized knowing that no filenames should be duplicated throughout any single text file.
text is an array of lines that make up the base of the total file.
lineNum holds an array of the line locations of the filename entries.
previousFiles is an array of previously used filenames, starting with what is already in the file.
files is a jagged 2-dimensional array of possible filenames where files[1] would be an array of all the possible filenames for the 2nd location
Here is an example of how it would work with 3 separate filename locations, the first one given 3 possible filenames, the second given 8 possible filenames, and the third given 3 possible filenames.
Oh and assume buildNewFile works.
int iterator = 0;
for (int a = 0; a < 3; a++)
{
for (int b = 0; b < 8; b++)
{
for (int c = 0; c < 3; c++)
{
iterator++;
text[lineNums[0]] = text[lineNums[0]].Replace(previousFiles[0], files[0][a]);
text[lineNums[1]] = text[lineNums[1]].Replace(previousFiles[0], files[0][a]);
text[lineNums[2]] = text[lineNums[2]].Replace(previousFiles[1], files[1][b]);
text[lineNums[3]] = text[lineNums[3]].Replace(previousFiles[1], files[1][b]);
text[lineNums[4]] = text[lineNums[4]].Replace(previousFiles[2], files[2][c]);
text[lineNums[5]] = text[lineNums[5]].Replace(previousFiles[2], files[2][c]);
previousFiles = new string[] { files[0][a], files[1][b], files[2][c] };
buildNewFile(text, Info.baseFolder + "networks\\" + Info.dsnFilename + iterator + ".dsn");
}
}
}
If you guys can help me, thank you so much, I just can't figure out how to do it recursively or anything. If you have any questions I'll answer them and edit up here to reflect that.
It took me a little while to figure out what you really wanted to do. This problem can be solved without recursion, the trick is to look at the data you have and get it into a more usable format.
Your "files" array is the one that is the most inconvenient. The trick is to transform the data into usable permutations. To do that, I suggest taking advantage of yield and using a method that returns IEnumerable. The code for it is here:
public IEnumerable<string[]> GenerateFileNameStream(string[][] files)
{
int[] current_indices = new int[files.Length];
current_indices.Initialize();
List<string> file_names = new List<string>();
while (current_indices[0] < files[0].Length)
{
file_names.Clear();
for (var index_index = 0; index_index < current_indices.Length; index_index++)
{
file_names.Add(files[index_index][current_indices[index_index]]);
}
yield return file_names.ToArray();
// increment the indices, trickle down as needed
for (var check_index = 0; check_index < current_indices.Length; check_index++)
{
current_indices[check_index]++;
// if the index hasn't rolled over, we're done here
if (current_indices[check_index] < files[check_index].Length) break;
// if the last location rolls over, then we are totally done
if (check_index == current_indices.Length - 1) yield break;
// reset this index, increment the next one in the next iteration
current_indices[check_index] = 0;
}
}
}
Basically, it keeps track of the current index for each row of the files 2D array and returns the file name at each current index. Then it increments the first index. If the first index rolls over, then it resets to 0 and increments the next index instead. This way we can iterate through every permutation of the file names.
Now, looking at the relationship between lineNum and files, I assume that each location in the file is copied to two lines. The rest of the code is here:
public void MakeItWork(string[][] files, int[] lineNum, string[] text, string[] previousFiles)
{
var iterator = 0;
var filenames = GenerateFileNameStream(files);
// work a copy of the text, assume the "previousFiles" are in this text
var text_copy = new string[text.Length];
foreach (var filenameset in filenames)
{
iterator++;
Array.Copy(text, text_copy, text.Length);
for (var line_index = 0; line_index < lineNum.Length; line_index++)
{
var line_number = lineNum[line_index];
text[line_number] = text[line_number].Replace(previousFiles[line_index], filenameset[line_index / 2]);
}
buildNewFile(text_copy, Info.baseFolder + "networks\\" + Info.dsnFilename + iterator + ".dsn");
}
}
This code just takes the results from the enumerator and generates the files for you. The assumption based on your sample code is that each filename location is used twice per file (since the lineNum array was twice as long as the files location count.
I haven't fully tested all the code, but the crux of the algorithm is there. The key is to transform your data into a more usable form, then process it. The other suggestion I have when asking a question here is to describe the problem more as a "problem" and not in the terms of your current solution. If you detailed the goal you are trying to achieve instead of showing code, you can get more insights into the problem.

Categories