Splitting an array into 2D or two arrays - c#

I have a text file that I am reading to pull out register values and what they contain.
2 lines from the array pulled out is: (full list is about 700)
0x0003 = 0x0069
0x0007 = 0x0078
I would like to split these into two arrays or one 2-dimensional array, whatever is best(I am new to using arrays)
My goal is to search the array for example for register 3, find the index then extract the information from the 2nd arrays corresponding index.
Here is my code so far ,
List<string> registerFullList1 = new List<string>();
for (int i = 0; i < 2000; i++)
{
string[] importStringArray1 = new string[2000];
importStringArray1[i] = importStringArray1[i] + objReader.ReadLine() + "\r\n";
//code to extract register info from string array
string listsplit1 = Regex.Match(importStringArray1[i], #"(?<= 0x)[0-9A-Fa-z\s\=]{13}").Value;
if (listsplit1.Contains("0x")) //code to add to list only registers and ignore empty lines
{
registerFullList1.Add(Convert.ToString(listsplit1));
}
}
int[] index = new int[2000]; // is there a way here that I don't have to assign 0,1,2,3 to each assignment?
index[0] = registerFullList1.FindIndex(x => x.StartsWith("0003 ="));
Register3.Text = Regex.Match(registerFullList1[index[0]], #"(?<= 0x)[0-9A-F]{4}").Value;
index[1] = registerFullList1.FindIndex(x => x.StartsWith("0007 ="));
Register7.Text = Regex.Match(registerFullList1[index[1]], #"(?<= 0x)[0-9A-F]{4}").Value;
This all works no problem and I am displaying the register content in text boxes. But I would like two arrays so it is more proper, one with register numbers and one with content. I cant figure it out, any help would be appreciated.
UPDATE
final code after reading answers,
List<string> registerNumberList = new List<string>();
List<string> registerContentList = new List<string>();
List<string> registerFullList = new List<string>();
for (int i = 0; i < 2000; i++)
{
string[] importStringArray1 = new string[2000];
importStringArray1[i] = importStringArray1[i] + objReader.ReadLine() + "\r\n";
string listsplit1 = Regex.Match(importStringArray1[i], #"(?<= 0x)[0-9A-Fa-z\s\=]{13}").Value; // #"(?<== 0x)[0-9A-F]{4}"
string listsplit2 = Regex.Match(importStringArray1[i], #"(?<= 0x)[0-9A-Fa-z\s\=]{4}").Value;// pulls out the register number from original array
string listsplit3= Regex.Match(importStringArray1[i], #"(?<== 0x)[0-9A-Fa-z\s\=]{4}").Value;//pulls out register content from original array
if (listsplit1.Contains("0x"))
{
registerNumberList.Add(Convert.ToString(listsplit3));//makes a list with register numbers
registerContentList.Add(Convert.ToString(listsplit2) );//makes a list with register content
registerFullList.Add(Convert.ToString(listsplit2) + "=" + Convert.ToString(listsplit3));//the full list
}
}
Dictionary <string, string> registers = registerFullList.Select(line => line.Split('=')
.ToArray())
.ToDictionary(items => items[0], items => items[1]); //joins the register numbers and content into a dictionary with just 4 decimal values for each
list1.Text = String.Join("\r\n", registerFullList);
list2.Text = registers["0010"]; // pulls out register info
Thanks guys

I suggest using Linq:
If you insist on the array:
int[][] result = File
.ReadLines(#"C:\myFile.txt")
.Select(line => line
.Split('=')
.Select(item => Convert.ToInt32(item, 16))
.ToArray())
.ToArray();
In case first index is unique one (and thus can serve as a key) you can materialize the data as a dictionary:
Dictionary<int, int> result = File
.ReadLines(#"C:\myFile.txt")
.Select(line => line
.Split('=')
.Select(item => Convert.ToInt32(item, 16))
.ToArray())
.ToDictionary(items => items[0], items => items[1]);
...
// value == 0x0078 (120)
int value = result[0x0007];

Try using a dictionary :
Dictionary<string, string> registersKeyValue = new Dictionary<string, string>();
string content = registersKeyValue
.Where(keyValuePair => keyValuePair.Key == "0x0003")
.FirstOrDefault()
.Value;

Related

making unique strings after getting value from hashset?

Okay So I have this Hashset that contains 3 items and I want to apply some logic on it such that I am able to append some predefined 3 values for the each item present inside the hashset
for example,
HashSet<string> hs = new HashSet<string>(); //it could be string or some other class object
hs.add("Red");
hs.add("Yellow");
hs.add("Blue");
//Some predefined values for those strings that I want to append to them
string[] str = {Alpha, Beta, Gamma}
The output I desire is:
unique strings associating "RedAlpha", "YellowBeta", "bluegamma"
for example s1 = "RedAlpha", s2 = "YellowBeta", s3 = "bluegamma";
I then want to apply some different logic to each of them later but then I guess that is a different thing
My Tried code
int count = 1;
int index = 0;
string s = "";
foreach(string strr in hs)
{
string s + count = strr + str[index]; // I don't know how to make new unique string
count++;
index++;
}
My other Tried Code,
foreach(string strr in hs)
{
string s = strr + str[index];
s = s + ","
index++;
}
s.split(",");
When you want to merge 2 collection together and perform some operation on them, use the Zip method. See this answer for an explanation of Zip method.
Here is how to achieve what you need:
HashSet<string> hs = new HashSet<string>();
hs.Add("Red");
hs.Add("Yellow");
hs.Add("Blue");
string[] str = { "Alpha", "Beta", "Gamma" };
List<KeyValuePair<string, string>> kvps =
hs.Zip(str, (left, right) => new KeyValuePair<string, string>(left, right))
.ToList();
If you want a dictionary, it is straight forward as well:
Dictionary<string, string> kvps =
hs.Zip(str, (left, right) => new { left, right })
.ToDictionary(x => x.left, x.right);
Put them in a list:
int index = 0;
var list = new List<string>();
foreach(string strr in hs)
{
list.Add(strr + str[index]);
index++;
}
Console.WriteLine(list[0]); //RedAlpha

split string array c#

So I have multiple arrays of strings. Within each array I have a string which uses '|' as a separator. What I need is to create a string with the first elements of the array up until the '|'.
So in the example I need 6485,6486,6487,6509,6510,6511,6533,6534,6535,|
Use String.Split() to split the original strings, then store the first ones in a separate array, then use String.Join() to concatenate them
string[] tempStrings = new string[stringArray.Length];
for(int i = 0; i < stringArray.Length; i++)
{
tempStrings[i] = stringArray[i].Split(#"|")[0];
}
string result = String.Join(",", tempStrings);
Using System.Linq :
string[] temp = new string[] { "1,2,3|4,5,6|7,8,9", "10,11,12|13,14,15", "16,17,18"};
var result = String.Join(",", temp.Select(x => x.Split('|').FirstOrDefault())
.ToList());
With null and empty values :
string[] temp = new string[] { "1,2,3|4,5,6|7,8,9", "10,11,12|13,14,15", "16,17,18", "", null };
var result = String.Join(",", temp.Select(x => x?.Split('|').FirstOrDefault())
.Where(x => !string.IsNullOrWhiteSpace(x))
.ToList());

C# 2 string arrays to List<string, string>

Assuming the 2 string arrays are the same length and not empty how can I make a List of the contents?
I had a Dictionary working, but now I need to be able to use duplicate keys so I am resorting to a List.
string[] files = svd.file.Split(",".ToCharArray());
string[] references = svd.references.Split(",".ToCharArray());
Dictionary<string, string> frDictionary = new Dictionary<string, string>();
frDictionary = files.Zip(rReferences, (s, i) => new { s, i })
.ToDictionary(item => item.s, item => item.i);
I could do it like:
List<string, string> jcList = new List<string, string>();
and then just have a double loop into the two arrays but I know a faster way must exist.
ILookup<string,string> myLookup =
files.Zip(rReferences, (s, i) => new { s, i })
.ToLookup(item => item.s, item => item.i);
will create a Dictionary-like structure that allows multiple values per key.
So
IEnumerable<string> foo = myLookup["somestring"];
A List containing elements with two strings each is simplest implemented with a
List<T>
and
T == Tuple<string,string>
Then use a loop to build your list from the two arrays:
string[] s1 =
{
"1", "2"
};
string[] s2 =
{
"a", "b"
};
var jcList = new List<Tuple<string,string>>();
for (int i = 0; i < s1.Length; i++)
{
jcList.Add(Tuple.Create(s1[i], s2[i]));
}
or using LINQ:
var jcList = s1.Select((t, i) => Tuple.Create(t, s2[i])).ToList();

Sorting a string based on prefixes

If you are given an array with random prefixes, like this:
DOG_BOB
CAT_ROB
DOG_DANNY
MOUSE_MICKEY
DOG_STEVE
HORSE_NEIGH
CAT_RUDE
HORSE_BOO
MOUSE_STUPID
How would i go about sorting this so that i have 4 different arrays/lists of strings?
So the end result would give me 4 string ARRAYS or lists with
DOG_BOB,DOG_DANNY,DOG_STEVE <-- Array 1
HORSE_NEIGH, HORSE_BOO <-- Array 2
MOUSE_MICKEY, MOUSE_STUPID <-- Array 3
CAT_RUDE, CAT_ROB <-- Array 4
sorry about the names i just made them up lol
var fieldNames = typeof(animals).GetFields()
.Select(field => field.Name)
.ToList();
List<string> cats = new List<string>();
List<string> dogs = new List<string>();
List<string> mice= new List<string>();
List<string> horse = new List<string>();
foreach (var n in fieldNames)
{
var fieldValues = typeof(animals).GetField(n).GetValue(n);"
//Here's what i'm trying to do, with if statements
if (n.ToString().ToLower().Contains("horse"))
{
}
}
So i need them to be splitted into STRING ARRAYS/STRING LISTS and NOT just strings
string[] strings = new string[] {
"DOG_BOB",
"CAT_ROB",
"DOG_DANNY",
"MOUSE_MICKEY",
"DOG_STEVE",
"HORSE_NEIGH",
"CAT_RUDE",
"HORSE_BOO",
"MOUSE_STUPID"};
string[] results = strings.GroupBy(s => s.Split('_')[0])
.Select(g => String.Join(",",g))
.ToArray();
Or maybe something like this
List<List<string>> res = strings.ToLookup(s => s.Split('_')[0], s => s)
.Select(g => g.ToList())
.ToList();
var groups = fieldNames.GroupBy(n => n.Split('_')[0]);
Usage
foreach(var group in groups)
{
// group.Key (DOG, HORSE, CAT, etc)
foreach(var name in group)
// all names groped by prefix
}
foreach (String s in strings)
{
if (s.StartsWith("CAT_")
cats.Add(s);
else if (s.StartsWith("HORSE_")
horses.Add(s);
// ...
}
Or:
foreach (String s in strings)
{
String[] split = s.Split(new Char [] { '_' });
if (split[0].Equals("CAT")
cats.Add(s);
else if (split[0].Equals("HORSE")
horses.Add(s);
// ...
}
But I would prefer the first one.
Algorithmically, I'd do the following:
Parse out all unique prefixes by using the "_" as your delimeter.
Loop through your list of prefixes.
2a. Retrieve any values that have your prefix (loop/find/regex/depends on structure)
2b. Place retrieved values in a List.
2c. Sort list.
Output your results, or do what you need with your collections.
You can order the list up front and sort by prefix:
string[] input = new string[] {"DOG_BOB","CAT_ROB","DOG_DANNY","MOUSE_MICKEY","DOG_STEVE","HORSE_NEIGH","CAT_RUDE","HORSE_BOO","MOUSE_STUPID"};
string[] sortedInput = input.OrderBy(x => x).ToArray();
var distinctSortedPrefixes = sortedInput.Select(item => item.Split('_')[0]).Distinct().ToArray();
Dictionary<string, string[]> orderedByPrefix = new Dictionary<string, string[]>();
for (int prefixIndex = 0; prefixIndex < distinctSortedPrefixes.Length; prefixIndex++)
{
string prefix = distinctSortedPrefixes[prefixIndex];
var group = input.Where(item => item.StartsWith(prefix)).ToArray();
orderedByPrefix.Add(prefix, group);
}
With LINQ, using something like
names.GroupBy(s => s.Substring(0, s.IndexOf("_"))) // group by prefix
.Select(g => string.Join(",", g)) // join each group with commas
.ToList(); // take the results
See it in action (some extra .ToArray() calls included for .NET 3.0 compatibility)
This LINQ expression does what you want.
var result = data.GroupBy(data.Split('_')[0])
.Select(group => String.Join(", ", group))
.ToList();
For a list of lists of strings use this expression.
var result = data.GroupBy(data.Split('_')[0])
.Select(group => group.ToList())
.ToList();

How to find the number of each elements in the row and store the mean of each row in another array using C#?

I am using the below code to read data from a text file row by row. I would like to assign each row into an array. I must be able to find the number or rows/arrays and the number of elements on each one of them.
I would also like to do some manipulations on some or all rows and return their values.
I get the number of rows, but is there a way to to loop something like:
*for ( i=1 to number of rows)
do
mean[i]<-row[i]
done
return mean*
var data = System.IO.File.ReadAllText("Data.txt");
var arrays = new List<float[]>();
var lines = data.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var lineArray = new List<float>();
foreach (var s in line.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries))
{
lineArray.Add(Convert.ToSingle(s));
}
arrays.Add(lineArray.ToArray());
}
var numberOfRows = lines.Count();
var numberOfValues = arrays.Sum(s => s.Length);
var arrays = new List<float[]>();
//....your filling the arrays
var averages = arrays.Select(floats => floats.Average()).ToArray(); //float[]
var counts = arrays.Select(floats => floats.Count()).ToArray(); //int[]
Not sure I understood the question. Do you mean something like
foreach (string line in File.ReadAllLines("fileName.txt")
{
...
}
Is it ok for you to use Linq? You might need to add using System.Linq; at the top.
float floatTester = 0;
List<float[]> result = File.ReadLines(#"Data.txt")
.Where(l => !string.IsNullOrWhiteSpace(l))
.Select(l => new {Line = l, Fields = l.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) })
.Select(x => x.Fields
.Where(f => Single.TryParse(f, out floatTester))
.Select(f => floatTester).ToArray())
.ToList();
// now get your totals
int numberOfLinesWithData = result.Count;
int numberOfAllFloats = result.Sum(fa => fa.Length);
Explanation:
File.ReadLines reads the lines of a file (not all at once but straming)
Where returns only elements for which the given predicate is true(f.e. the line must contain more than empty text)
new { creates an anonymous type with the given properties(f.e. the fields separated by comma)
Then i try to parse each field to float
All that can be parsed will be added to an float[] with ToArray()
All together will be added to a List<float[]> with ToList()
Found an efficient way to do this. Thanks for your input everybody!
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);
}
});
var rowTotal = new double[numbers.Count];
var rowMean = new double[numbers.Count];
var totalInRow = new int[numbers.Count()];
for (var row = 0; row < numbers.Count; row++)
{
var values = numbers[row].ToArray();
rowTotal[row] = values.Sum();
rowMean[row] = rowTotal[row] / values.Length;
totalInRow[row] += values.Length;
}

Categories

Resources