I'm attempting to parse a pipe delimited line of text from a file - HL7 message segment - to make the segment a property of an HL7 message object.
I think I"m fundamentally not understanding the concept of n-dimensional arrays...
The segment looks like this
MSH|^~\&||X530^X530^FID|ERIC^NSCC^RSSI|NSCCH|....
I want to create an array thusly;
First item in the array = {"0","MSH"}
Next item in the array = {"1,", "^~\&"}
Next item in the array = {"2,", null}
Next item in the array = {"3,", "X530^X530^FID"}
I get error message:
private string [,] ParseSegment(string ms)
{
int i = 0;
string[] segmentFields = ms.Split('|');//fields for this segment
int arrayLength = segmentFields.Length;
string[,] fieldAndIndex = new string[arrayLength,1];
foreach (string field in segmentFields)
{
fieldAndIndex [i,i] = {{ i,field} };//I'm not sure what to do here!!!!
}
return fieldAndIndex;
}
Each sub array of your 2D array has 2 items (right?), so you should have a 2 instead of a 1 as the length:
string[,] fieldAndIndex = new string[arrayLength, 2];
Since you want a counter variable I in the loop, you should not use a foreach loop:
for (int i = 0 ; i < arrayLength ; i++) {
// here you want the first item of the subarray to be i, and the second item to be the corresponding segment
fieldAndIndex[i, 0] = i.ToString();
fieldAndIndex[i, 1] = segmentFields[i];
}
Also, I don't think a 2D array is suitable here. Storing the index of each element (which is what you seem to be trying to do) is unnecessary, because fieldAndIndex[x, 0] will always be the same as x!
You might want to use a simple 1D array instead. There are other data structures that might be useful:
Dictionary<int, string>
(int, string)[]
string[][]
To understand the basic array in your case you can consider the array to be a 2D Matrix. Similarly you can consider a 3D array a cube. What you are trying to do is add two item in one place
fieldAndIndex [i,i] = {{ i,field} };
So during the first iteration the notation [i,i] evaluates to [0,0] which means the first element in the first row.
The proper way to insert these both can be done as shown by the given answer
fieldAndIndex [i,i] = i.ToString();
fieldAndIndex [i,++i] = field.ToString();
I hope this resolves your issue it is better to go through some research on multi dimensional arrays. This and This are some good links to get started on these arrays.
private string [] ParseSegment(string ms) //you do not need 2d array for that
{
int i = 0;
string[] segmentFields = ms.Split('|');//fields for this segment
int arrayLength = segmentFields.Length;
string[] fieldAndIndex = new string[arrayLength];
foreach (string field in segmentFields)
{
fieldAndIndex [i] = field;
i++;
}
return fieldAndIndex;
}
You do not need 2d array(matrix) to parse that (calling fieldAndIndex[n] will just give it's value - fieldAndIndex[1] == "^~\&""), but if you really need to :
private string [,] ParseSegment(string ms)
{
int i = 0;
string[] segmentFields = ms.Split('|');//fields for this segment
int arrayLength = segmentFields.Length;
string[,] fieldAndIndex = new string[arrayLength,2];
foreach (string field in segmentFields)
{
fieldAndIndex [i][0] = i;
fieldAndIndex [i][1] = field;
i++;
}
return fieldAndIndex;
}
While I dont understand why you would want a 2 dimentional array.
new string[arrayLength,1]; should be new string[arrayLength,2];
[i,i] expects 1 element, not 2. Also you need to use [i,0] and [i,1]
private string [,] ParseSegment(string ms)
{
int i = 0;
string[] segmentFields = ms.Split('|');//fields for this segment
int arrayLength = segmentFields.Length;
string[,] fieldAndIndex = new string[arrayLength,2];
foreach (string field in segmentFields)
{
fieldAndIndex [i,0] = i.ToString();
fieldAndIndex [i,1] = field;
i++;
}
return fieldAndIndex;
}
Related
Given the following code:
List<int> Data = new List<int>();
Data.Add(1);
Data.Add(2);
Array[] tmp = new Array[Data.Count];
tmp[0] = Data.ToString().ToArray();
How to access the Data array in tmp[0]?
I have try tmp[0,0] or tmp[0].Data[0] but it doesn't work and gives me an error.
simple is can I add array to array onedimesion? if can how?
Just write
Array tmp;
tmp = Data.ToArray();
for(int x = 0; x < tmp.Length; x++)
Console.WriteLine(tmp.GetValue(x));
However I recommend to stick at using a strong typed List
Going deeper along this slippery path you could create an Array of Array (oh boy this start to get confusing)
// Create an array of two Array
Array[] tmp = new Array[Data.Count];
// First array set to the integer array
tmp[0] = Data.ToArray();
// Second array of strings
tmp[1] = new string[5];
// Set first element of the second array to a string
tmp[1].SetValue("Steve", 0);
Again, forget this approach and use more advanced collection classes like
Dictionary
Hashset
Tuple
If you want to access your data a a specific position just use
Data[Index]
if you realy want to use a array you can do
int[] array = Data.ToArray();
Must do like this.
List<int> Data = new List<int>();
Data.Add(1);
Data.Add(2);
int[] tmp = Data.ToArray();
Simply you can use
var array=Data.ToArray();
and if you want to add new item in array you might want to resize it first using
Array.Resize(ref array, array.Count() + 1);
array[array.Count()]=//your items here..
When adding. deleting use List<T>:
List<int> Data = new List<int>();
// Add item after item
Data.Add(1);
Data.Add(2);
// Add whole range of items, e.g. an array
Data.AddRange(new int[] {3, 4, 5});
int v = Data[0];
Data[0] = v + 10;
Console.Write(String.Join(", ", Data));
Finally, when you to have an array
int[] tmp = Data.ToArray();
// you still can read an item
int x = tmp[0];
// and write it
tmp[0] = x - 10;
But remember, you can't do tmp.Add() or tmp.RemoveAt()
I would like to programmatically add or remove some elements to a string array in C#, but still keeping the items I had before, a bit like the VB function ReDim Preserve.
The obvious suggestion would be to use a List<string> instead, which you will have already read from the other answers. This is definitely the best way in a real development scenario.
Of course, I want to make things more interesting (my day that is), so I will answer your question directly.
Here are a couple of functions that will Add and Remove elements from a string[]...
string[] Add(string[] array, string newValue){
int newLength = array.Length + 1;
string[] result = new string[newLength];
for(int i = 0; i < array.Length; i++)
result[i] = array[i];
result[newLength -1] = newValue;
return result;
}
string[] RemoveAt(string[] array, int index){
int newLength = array.Length - 1;
if(newLength < 1)
{
return array;//probably want to do some better logic for removing the last element
}
//this would also be a good time to check for "index out of bounds" and throw an exception or handle some other way
string[] result = new string[newLength];
int newCounter = 0;
for(int i = 0; i < array.Length; i++)
{
if(i == index)//it is assumed at this point i will match index once only
{
continue;
}
result[newCounter] = array[i];
newCounter++;
}
return result;
}
If you really won't (or can't) use a generic collection instead of your array, Array.Resize is c#'s version of redim preserve:
var oldA = new [] {1,2,3,4};
Array.Resize(ref oldA,10);
foreach(var i in oldA) Console.WriteLine(i); //1 2 3 4 0 0 0 0 0 0
Don't use an array - use a generic List<T> which allows you to add items dynamically.
If this is not an option, you can use Array.Copy or Array.CopyTo to copy the array into a larger array.
Since arrays implement IEnumerable<T> you can use Concat:
string[] strArr = { "foo", "bar" };
strArr = strArr.Concat(new string[] { "something", "new" });
Or what would be more appropriate would be to use a collection type that supports inline manipulation.
Use List<string> instead of string[].
List allows you to add and remove items with good performance.
What's abaut this one:
List<int> tmpList = intArry.ToList();
tmpList.Add(anyInt);
intArry = tmpList.ToArray();
One liner:
string[] items = new string[] { "a", "b" };
// this adds "c" to the string array:
items = new List<string>(items) { "c" }.ToArray();
You should take a look at the List object. Lists tend to be better at changing dynamically like you want. Arrays not so much...
You can use a generic collection, like List<>
List<string> list = new List<string>();
// add
list.Add("element");
// remove
list.Remove("element");
You can use this snippet:
static void Main(string[] args)
{
Console.WriteLine("Enter number:");
int fnum = 0;
bool chek = Int32.TryParse(Console.ReadLine(),out fnum);
Console.WriteLine("Enter number:");
int snum = 0;
chek = Int32.TryParse(Console.ReadLine(),out snum);
Console.WriteLine("Enter number:");
int thnum = 0;
chek = Int32.TryParse(Console.ReadLine(),out thnum);
int[] arr = AddToArr(fnum,snum,thnum);
IOrderedEnumerable<int> oarr = arr.OrderBy(delegate(int s)
{
return s;
});
Console.WriteLine("Here your result:");
oarr.ToList().FindAll(delegate(int num) {
Console.WriteLine(num);
return num > 0;
});
}
public static int[] AddToArr(params int[] arr) {
return arr;
}
I hope this will help to you, just change the type
I have a list of numbers on a textbox like so (the numbers used are just examples):
1 1 1
2 2 2
...
So I want to convert that into a 2d array. I know to use .ToArray() or Regex.Split() for 1d lists but am not sure how to use that for 2d. I've also tried to use those functions on a string[] array to make it 2d but there was an error.
Also, the array is supposed to be an int[,] so that the values in the array can be compared. Any help would be appreciated, thanks!
Here you go, if you don't understand any part please ask in the comments:
// assuming the numbers are in perfect 2D format in textBox (only 1 newline separates the lines, only 1 space separates numbers in each line and all lines have the same amount of numbers)
string textWithNumbers = textBox.Text;
// first put all lines into an string array
string[] allLines = textWithNumbers.Split(new string[]{Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
// calculate 2D array's dimension lengths, and initialize the 2Darray
int rowCount = allLines.Length;
int columnCount = ((allLines[0].Length + 1) / 2);
int[,] twoDArray = new int[rowCount, columnCount];
// we then iterate through the 2D array
for (int row = 0; row < rowCount; row++)
{
// parse each number from string format to integer format & assign it to the corresponding location in our 2D array
string[] line = allLines[row].Split(' ');
for (int column = 0; column < columnCount; column++)
{
twoDArray[row, column] = int.Parse(line[column]);
}
}
This will give you a nice jagged 2D array that doesn't depend on all the text boxes having the same length. If you need them to all be the same length, it's trivial to check.
string[] data = // text input from all the text boxes
var result = data.Select(x => x.Split(' ')
.Select(y => int.Parse(y)).ToArray())
.ToArray();
Result is not quite an int[,] but an int[int[]], which is practically the same thing.
Of course, you need to deal with input validation or error handling.
Let me first start with the most naive solution, this makes very few assumptions about the data entered by the user. For example, it does not assume that every row has the same number of entries etc. So this could be optimized for those special conditions that you might know hold true or can enforce before running this routine.
// This is the data from the textbox
// hardcoded here for demonstration
string data = "1 1 1" + Environment.NewLine
+ "2 2 2" + Environment.NewLine
+ "12 12 12";
// First we need to determine the size of array dimension
// How many rows and columns do we need
int columnCount;
int rowCount;
// We get the rows by splitting on the new lines
string[] rows = data.Split(new string[]{Environment.NewLine},
StringSplitOptions.RemoveEmptyEntries);
rowCount = rows.Length;
// We iterate through each row to find the max number of items
columnCount = 0;
foreach (string row in rows)
{
int length = row.Split(' ').Length;
if (length > columnCount) columnCount = length;
}
// Allocate our 2D array
int[,] myArray = new int[rowCount, columnCount];
// Populate the array with the data
for (int i = 0; i < rowCount; ++i)
{
// Get each row of data and split the string into the
// separate components
string[] rowData = rows[i].Split(' ');
for (int j = 0; j < rowData.length; ++j)
{
// Convert each component to an integer value and
// enter it into the 2D array
int value;
if (int.TryParse(rowData[j], out value))
{
myArray[i, j] = value;
}
}
}
Given the above where we are considering the possibility of each row not having the same number of elements, you might consider using a sparse array int[][] which coincidentally also yield better performance in .NET.
How can I define a dynamic array in C#?
C# doesn't provide dynamic arrays. Instead, it offers List class which works the same way.
To use lists, write at the top of your file:
using System.Collections.Generic;
And where you want to make use of a list, write (example for strings):
List<string> mylist = new List<string>();
mylist.Add("First string in list");
Take a look at Array.Resize if you need to resize an array.
// Create and initialize a new string array.
String[] myArr = {"The", "quick", "brown", "fox", "jumps",
"over", "the", "lazy", "dog"};
// Resize the array to a bigger size (five elements larger).
Array.Resize(ref myArr, myArr.Length + 5);
// Resize the array to a smaller size (four elements).
Array.Resize(ref myArr, 4);
Alternatively you could use the List class as others have mentioned. Make sure you specify an initial size if you know it ahead of time to keep the list from having to resize itself underneath. See the remarks section of the initial size link.
List<string> dinosaurs = new List<string>(4);
Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
dinosaurs.Add("Tyrannosaurus");
dinosaurs.Add("Amargasaurus");
dinosaurs.Add("Mamenchisaurus");
dinosaurs.Add("Deinonychus");
If you need the array from the List, you can use the ToArray() function on the list.
string[] dinos = dinosaurs.ToArray();
C# does provide dynamic arrays and dynamic array manipulation. The base of an array is dynamic and can be modified with a variable. You can find the array tutorial here (https://msdn.microsoft.com/en-us/library/aa288453%28v=vs.71%29.aspx). I have also included code that demonstrates an empty set array and a dynamic array that can be resized at run time.
class Program
{
static void Main(string[] args)
{
int x = Convert.ToInt32(Console.ReadLine());
int y = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(x);
{
int[] dynamicArray1 = { };//empty array
int[] numbers;//another way to declare a variable array as all arrays start as variable size
numbers = new int[x];//setting this array to an unknown variable (will be user input)
for (int tmpInt = 0; tmpInt < x; tmpInt++)//build up the first variable array (numbers)
{
numbers[tmpInt] = tmpInt;
}
Array.Resize(ref numbers,y);// resize to variable input
dynamicArray1 = numbers;//set the empty set array to the numbers array size
for (int z = 0; z < y; z++)//print to the new resize
{
Console.WriteLine(numbers[z].ToString());//print the numbers value
Console.WriteLine(dynamicArray1[z].ToString());//print the empty set value
}
}
Console.Write("Dynamic Arrays ");
var name = Console.ReadLine();
}
}
Actually you can have Dynamic Arrays in C# it's very simple.
keep in mind that the response to your question above is also correct you could declare a
List Generic
The way to Create a Dynamic Array would be to declare your Array for example
string[] dynamicArry1 = { };//notice I did not declare a size for the array
List<String> tmpList = new List<string>();
int i = 1;
for(int tmpInt = 0; tmpInt < 5; tmpInt++)
{
tmpList.Add("Testing, 1.0." + tmpInt + ", 200, 3.4" + tmpInt +"," + DateTime.Now.ToShortDateString());
//dynamicArry1[tmpInt] = new string[] { tmpList[tmpInt].ToCharArray() };
}
dynamicArry1 = tmpList.ToArray();
how about ArrayList ?
If I'm not wrong ArrayList is an implementation of dynamic arrays
Example of Defining Dynamic Array in C#:
Console.WriteLine("Define Array Size? ");
int number = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter numbers:\n");
int[] arr = new int[number];
for (int i = 0; i < number; i++)
{
arr[i] = Convert.ToInt32(Console.ReadLine());
}
for (int i = 0; i < arr.Length; i++ )
{
Console.WriteLine("Array Index: "+i + " AND Array Item: " + arr[i].ToString());
}
Console.ReadKey();
like so
int nSize = 17;
int[] arrn = new int[nSize];
nSize++;
arrn = new int[nSize];
Say I have a rectangular string array - not a jagged array
string[,] strings = new string[8, 3];
What's the best way to extract a one-dimensional array from this (either a single row or a single column)? I can do this with a for loop, of course, but I'm hoping .NET has a more elegant way built in.
Bonus points for converting the extracted string array to an object array.
You can cast a string array to an object array trivially - going the other way doesn't work. The actual extraction has to use a for loop though, as far as I can see: Array.Copy requires the source and target ranks to be the same, and Buffer.BlockCopy only works for value type arrays. It does seem odd though...
You can use LINQ to extra a row or column in a single statement, although it will be inefficient (as it'll build up a list internally, then have to convert it to an array - if you do it yourself you can preallocate the array to the right size and copy directly).
Copying a row (rowNum is the row to be copied):
object[] row = Enumerable.Range(0, rowLength)
.Select(colNum => (object) stringArray[rowNum, colNum])
.ToArray();
Copying a column (colNum is the column to be copied):
object[] column = Enumerable.Range(0, columnLength)
.Select(rowNum => (object) stringArray[rowNum, colNum])
.ToArray();
I'm not sure that this is really any better/simpler than a foreach loop though - particularly if you write an ExtractRow method and an ExtractColumn method and reuse them.
For a rectangular array:
string[,] rectArray = new string[3,3] {
{"a", "b", "c"},
{"d", "e", "f"},
{"g", "h", "i"} };
var rectResult = rectArray.Cast<object>().ToArray();
And for a jagged array:
string[][] jaggedArray = {
new string[] {"a", "b", "c", "d"},
new string[] {"e", "f"},
new string[] {"g", "h", "i"} };
var jaggedResult = jaggedArray.SelectMany(s => s).Cast<object>().ToArray();
I'd just like to clarify (given the example and what's being asked).
A jagged array is an array of arrays and is declared like so:
string[][] data = new string[3][];
data[0] = new string[] { "0,[0]", "0,[1]", "0,[2]" };
data[1] = new string[] { "1,[0]", "1,[1]", "1,[2]" ];
data[2] = new string[] { "2,[0]", "1,[1]", "1,[2]" };
Versus a rectangular array being defined as a single array that holds multiple dimensions:
string[,] data = new string[3,3];
data[0,0] = "0,0";
data[0,1] = "0,1";
data[0,2] = "0,2";
...etc
Because of this, a jagged array is IQueryable/IEnumerable because you can iterate over it to receive an array at each iteration. Whereas a rectangular array is not IQueryable/IEnumerable because elements are addressed in full dimension (0,0 0,1..etc) so you won't have the ability to use Linq or any predefined functions created for Array in that case.
Though you can iterate over the array once (and achieve what you want) like this:
/// INPUT: rowIndex, OUTPUT: An object[] of data for that row
int colLength = stringArray.GetLength(1);
object[] rowData = new object[colLength];
for (int col = 0; col < colLength; col++) {
rowData[col] = stringArray[rowIndex, col] as object;
}
return rowData;
/// INPUT: colIndex, OUTPUT: An object[] of data for that column
int rowLength = stringArray.GetLength(0);
object[] colData = new object[rowLength];
for (int row = 0; r < rowLength; row++) {
colData[row] = stringArray[row, colIndex] as object;
}
return colData;
Hope this helps :)
LINQ is the answer
static object[] GetColumn(string[][] source, int col) {
return source.Iterate().Select(x => source[x.Index][col]).Cast<object>().ToArray();
}
static object[] GetRow(string[][] source, int row) {
return source.Skip(row).First().Cast<object>().ToArray();
}
public class Pair<T> {
public int Index;
public T Value;
public Pair(int i, T v) {
Index = i;
Value = v;
}
}
static IEnumerable<Pair<T>> Iterate<T>(this IEnumerable<T> source) {
int index = 0;
foreach (var cur in source) {
yield return new Pair<T>(index, cur);
index++;
}
}
Rows can be copied easily using Array.Copy:
int[][] arDouble = new int[2][];
arDouble[0] = new int[2];
arDouble[1] = new int[2];
arDouble[0][0] = 1;
arDouble[0][1] = 2;
arDouble[1][0] = 3;
arDouble[1][1] = 4;
int[] arSingle = new int[arDouble[0].Length];
Array.Copy(arDouble[0], arSingle, arDouble[0].Length);
This will copy the first row into the single Dimension array.
i made extention method. i dont know about the performance .
public static class ExtensionMethods
{
public static string[] get1Dim(this string[,] RectArr, int _1DimIndex , int _2DimIndex )
{
string[] temp = new string[RectArr.GetLength(1)];
if (_2DimIndex == -1)
{
for (int i = 0; i < RectArr.GetLength(1); i++)
{ temp[i] = RectArr[_1DimIndex, i]; }
}
else
{
for (int i = 0; i < RectArr.GetLength(0); i++)
{ temp[i] = RectArr[ i , _2DimIndex]; }
}
return temp;
}
}
usage
// we now have this funtionaliy RectArray[1, * ]
// -1 means ALL
string[] _1stRow = RectArray.get1Dim( 0, -1) ;
string[] _2ndRow = RectArray.get1Dim( 1, -1) ;
string[] _1stCol = RectArray.get1Dim( -1, 0) ;
string[] _2ndCol = RectArray.get1Dim( -1, 1) ;