Split string into 2D array - c#

I have .txt file with 10 954 lines in the format of 6,4:10
I need to load that .txt file with StreamReader and split every line at ':' into 2D array.
To look like this
[6,4 10]
[5,2 15]
[9,3 20]
So i can later on count each column and place it in a particular category.
This is the furthest i got so far
StreamReader ulaz = new StreamReader("C:\\Users\\Core\\Desktop\\podaciC.txt");
string[] polje = new string[10954];
while (!ulaz.EndOfStream)
{
for (int i = 0; i < polje.GetLength(0); i++)
{
polje[i] = ulaz.ReadLine();
}
}
ulaz.Close();
foreach (string s in polje)
{
Console.WriteLine(s);
}
Console.ReadKey();

Here is documentation for the ReadLine() method of the StreamReader: https://msdn.microsoft.com/da-dk/library/system.io.streamreader.readline(v=vs.110).aspx
Here is documentation for the Split() method of the String: https://msdn.microsoft.com/en-us/library/system.string.split(v=vs.110).aspx
You can solve this using those methods.
I would provide code, but that wouldn't be ethical since you haven't indicated that you've tried to solve this problem. I can help you solve your homework, but I won't solve it for you.

No need to fight with arrays and StreamReader. Easy to understand example:
using System.Collections.Generic;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main (string[] args)
{
var filePath = "C:\\Users\\Core\\Desktop\\podaciC.txt";
var result = new List<KeyValuePair<decimal, int>> (11000); // create list with initial capacity
var lines = File.ReadLines (filePath); // allows to read file line by line (without loading entire file into memory)
foreach (var line in lines)
{
string[] splittedLine = line.Split (':'); // split line into array of two elements
decimal key = decimal.Parse (splittedLine[0]); // parse first element
int value = int.Parse (splittedLine[1]); // parse second element
var kvp = new KeyValuePair<decimal, int> (key, value); // create tuple
result.Add (kvp);
}
}
}
}
I suggest you to create custom class like LineParser or something which will handle errors for invalid lines etc.

My example file uses these strings in it one string on each line:
6,4:10
6,4:10
6,4:10
6,4:10
Use Linq to get all lines and split them based on :
Get all lines and every line will be represented by a string all lines make up one array of strings
then select these result and split the string by and : on every index of the string array (lines).
Convert the the IEnumerable of string[] to array
string[][] array = File.ReadAllLines("C:\\t\\My File2.txt")
.Select(x => x.Split(':'))
.ToArray();
Out putting values to the console:
int counter = 0;
foreach (var rows in array)
{
foreach (var number in rows)
{
Console.Write("Number row {0} = {1}\t", counter, number);
}
Console.WriteLine();
counter++;
}
How the array looks:
string[4][]
{
string[2] { [0] => 6,4 [1] => 10 }
string[2] { [0] => 6,4 [1] => 10 }
string[2] { [0] => 6,4 [1] => 10 }
string[2] { [0] => 6,4 [1] => 10 }
}
Console Output
Number row 0 = 6,4 Number row 0 = 10
Number row 1 = 6,4 Number row 1 = 10
Number row 2 = 6,4 Number row 2 = 10
Number row 3 = 6,4 Number row 3 = 10

Related

Selecting from string from 2nd array based on 1st array results

I'm looking to make selections from a second array, based on the results in my first array. The first array stores integers of the position of certain column headers reside in a csv.
var path = #"C:\Temp\file.csv";
using (TextFieldParser csvImport = new TextFieldParser(path))
{
csvImport.CommentTokens = new string[] { "#" };
csvImport.SetDelimiters(new string[] { "," });
csvImport.HasFieldsEnclosedInQuotes = true;
string[] header = csvImport.ReadFields();
foreach (string colheader in header)
{
index = index + 1; //this bit will return where my column headers are in the header line
if (colheader == "FirstColumn")
{
key = (index - 1); //stores int of my result
}
else if (colheader == "SecondColumn")
{
secondkey = (index - 1); //stores int of my result
}
}
csvImport.ReadLine(); //Behaves as carriage line return, this moves to position 2 before loop
while (!csvImport.EndOfData)
{
//Read each field, build Sql Statement
string[] fields = csvImport.ReadFields();
string MyKey = fields[1]; //Currently this is static pos 1 I want it to be the result of key
string MySecondKey = fields[74]; //Currently this is static pos 74 I want it to be the result of SecondKey
}
}
is there a simple way of assigning a variable into the [] to ad hoc pick out my array based on other variables at my disposal?
I've edited the question slightly as what I am looking to achieve is picking the field from a csv line based on the indexes from the first arra
//Read each field, build Sql Statement
string[] fields = csvImport.ReadFields();
string MyKey = fields[1]; //Currently this is static pos 1 I want it to be the result of key
string MySecondKey = fields[74]; //Currently this is static pos 74 I want it to be the result of SecondKey
Give the items in your second array an index (i here), then get all items that their index is in first array:
secondArray.Select((x,i) => new {x, i})
.Where(z => firstArray.Contains(z.i))
.Select(z => z.x);
and here is a live demo
(of course the type of second array is not important and I have used string[] just for simplicity, and it can be an array of a class, ... )

How to determine which line is longest by string in textbox

Trying to find the longest line by string in a textbox (multi-line). Longest will return the number of the line, for example:
line 1: good day, world
line 2: good evening world
line 3: good morning, world
the longest string found in textbox will return the number of the line which is line 3 something like MessageBox("MAX: 3") or show multiple lines if found same string.
Note: count " " space too.
so far i tried this way:
string[] stringArray = textBox1.Text.Split(' ');
var Maximum = "";
var Minimum = textBox1.Lines[0];
foreach (string line in textBox1.Lines)
{
int index = line.IndexOf(textBox1.Text);
if (index > 0)
{
if (Minimum.Length > line.Length)
{
Minimum = line;
}
if (Maximum.Length < line.Length)
{
Maximum = line;
}
MessageBox.Show(string.Format("MAX: {0} ", index));
}
but for some reason it won't show it. Any idea why?
Your code splits the text of the textbox at spaces - you get "words". Then you foreach over all lines. Somehow you search the full text of your box inside of one line of the splitted text of your box. This can not work unless your textbox contains only 1 line without any newlines in it but then the whole thing does not make any sense anymore.
Use textBox1.Lines and check all lines for lenght, use the longest:
int i = 0;
int maxLen = -1;
int maxIndex = - 1;
foreach (var l in textBox1.Lines)
{
if (l.Length > maxLen)
{
maxLen = l.Length;
maxIndex = i;
}
i++;
}
// this will only capture the first line if multiple are same length
// maxLen holds the length of the longest line, maxIndex the index of it
If you want it fancier, use Linq:
You can use IEnumerable<T>.Select() for that - it has an overload that gives you the index as well. You create an anonymous type, OrderByDescending() it accordingly, get the Max() value from it and sort out Where() the length has this max value - you could shorten it without anonymous type but I think this way its clearer what happens:
using System;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
string[] stringArray = new[] { // you get this array from Textbox.Lines
"one line of text",
"second line with more text",
"short line",
"very long line with text and more text",
"very long line with text and more text" };
var sorted = stringArray
.Select((text, index) => new {Index=index, Text=text, Length=text.Length })
.OrderByDescending(ano => ano.Length)
.ToList(); // order by lenght descending
var maxLength = sorted.Max(ano => ano.Length); // get max length
var maxOnes = sorted.Where(ano => ano.Length == maxLength);
foreach (var ano in sorted)
Console.WriteLine(
$"{ano.Index} has length {ano.Length} and text of '{ano.Text}'");
Console.WriteLine(
$"The longest ones had indexes: {string.Join(",",
maxOnes.Select(ano => ano.Index))}");
Console.ReadLine();
}
}
Output:
3 has length 38 and text of 'very long line with text and more text'
4 has length 38 and text of 'very long line with text and more text'
1 has length 26 and text of 'second line with more text'
0 has length 16 and text of 'one line of text'
2 has length 10 and text of 'short line'
The longest ones had indexes: 3,4
Keeping things simple, this should do the job:
Int32 index = 0;
Int32 maxLength = 0;
String[] lines = textBox1.Lines;
for (Int32 i = 0; i < lines.Length; ++i)
{
Int32 currLength = lines[i].Length;
if (currLength > maxLength)
{
maxLength = currLength;
index = i;
}
}
MessageBox.Show(String.Format("MAX: {0}", index));
Alternatively, using LINQ and OrderByDescending together with IndexOf, you can proceed with the following code:
Int32 index = textBox1.Lines.IndexOf(textBox1.Lines.OrderByDescending(x => x.Length).First());
MessageBox.Show(String.Format("MAX: {0}", index));
Using LINQ will make this easy. Just order the lines by their length and use the last one because the longest will be at the end.
var lines = textBox1.Lines.ToList();
var longest = lines.OrderBy(line => line.Length).Last();
var index = lines.IndexOf(longest);
try Orderby and where:
var stringOrdered = textBox1.Lines.OrderByDescending(t => t.Length);
var mostLargeStrings = stringOrdered.Where(str=> str.Length == stringOrdered.First().Length);
var index = 0;
foreach(var TXT in mostLargeStrings)
{
index = Array.IndexOf(textBox1.Lines, TXT, index+1);
MessageBox.Show(string.Format("MAX: {0} ",index));
}
the code, first order the text strings from the longest to the shortest and then take the ones with the same length as the first one, then we search for their index in textbox Lines

Split big text string into small ones

I'm reading text file into one string and then spliting the whole file into array of strings with this code:
string[] split_text = Regex.Split(whole_text, #"\W+");
But when I do that every word is alone on one index and I don't want that.
I want biger string on one index let say about 10 words on one index in array and then 10 words on second index and so on.
So if I read file of 90 words I want to have size of array 9 and on every index 10 words.
You can use Batch method:
string[] split_text = Regex.Split(whole_text, #"\W+")
.Batch(10)
.Select(x => string.Concat(x))
.ToArray();
ok there is full sollution :
class Program
{
static void Main(string[] args)
{
List<string> result = new List<string>();
string text = "Now im checking first ten chars from sentence and some random chars : asdasdasdasdasdasdasdasd";
try
{
for (int i = 0; i < text.Length; i = i + 10)
{
string res = text.Substring(i,10);
result.Add(res);
Console.WriteLine(res);
}
}
catch (Exception)
{
}
}
}
I recommend use List<string> instead of array of strings.

Splitting string into an array on 16th char [duplicate]

This question already has answers here:
Splitting a string into chunks of a certain size
(39 answers)
Split string after certain character count
(4 answers)
Closed 8 years ago.
I have a text file with various 16 char strings both appended to one another and on separate lines. I've done this
FileInfo f = new FileInfo("d:\\test.txt");
string FilePath = ("d:\\test.txt");
string FileText = new System.IO.StreamReader(FilePath).ReadToEnd().Replace("\r\n", "");
CharCount = FileText.Length;
To remove all of the new lines and create one massively appended string. I need now to split this massive string into an array. I need to split it up on the consecutive 16th char until the end. Can anyone guide me in the right direction? I've taken a look at various methods in String such as Split and in StreamReader but am confused as to what the best way to go about it would be. I'm sure it's simple but I can't figure it out.
Thank you.
Adapting the answer from here:
You could try something like so:
string longstr = "thisisaverylongstringveryveryveryveryverythisisaverylongstringveryveryveryveryvery";
IEnumerable<string> splitString = Regex.Split(longstr, "(.{16})").Where(s => s != String.Empty);
foreach (string str in splitString)
{
System.Console.WriteLine(str);
}
Yields:
thisisaverylongs
tringveryveryver
yveryverythisisa
verylongstringve
ryveryveryveryve
ry
One possible solution could look like this (extracted as extension method and made dynamic, in case different token size is needed and no hard-coded dependencies):
public static class ProjectExtensions
{
public static String[] Chunkify(this String input, int chunkSize = 16)
{
// result
var output = new List<String>();
// temp helper
var chunk = String.Empty;
long counter = 0;
// tokenize to 16 chars
input.ToCharArray().ToList().ForEach(ch =>
{
counter++;
chunk += ch;
if ((counter % chunkSize) == 0)
{
output.Add(chunk);
chunk = String.Empty;
}
});
// add the rest
output.Add(chunk);
return output.ToArray();
}
}
The standard usage (16 chars) looks like this:
// 3 inputs x 16 characters and 1 x 10 characters
var input = #"1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890";
foreach (var chunk in input.Chunkify())
{
Console.WriteLine(chunk);
}
The output is:
1234567890ABCDEF
1234567890ABCDEF
1234567890ABCDEF
1234567890
Usage with different token size:
foreach (var chunk in input.Chunkify(13))
{
Console.WriteLine(chunk);
}
and the corresponding output:
1234567890ABC
DEF1234567890
ABCDEF1234567
890ABCDEF1234
567890
It is not a fancy solution (and could propably be optimised for speed), but it works and it is easy to understand and implement.
Create a list to hold your tokens. Then get subsequent substrings of length 16 and add them to the list.
List<string> tokens = new List<string>();
for(int i=0; i+16<=FileText.Length; i+=16) {
tokens.Add(FileText.Substring(i,16));
}
As mentioned in the comments, this ignores the last token if it has less than 16 characters. If you want it anyway you can write:
List<string> tokens = new List<string>();
for(int i=0; i<FileText.Length; i+=16) {
int len = Math.Min(16, FileText.Length-i));
tokens.Add(FileText.Substring(i,len);
}
Please try this method. I haven't tried it , but used it once.
int CharCount = FileText.Length;
int arrayhold = (CharCount/16)+2;
int count=0;
string[] array = new string[arrayhold];
for(int i=0; i<FileText.Length; i+=16)
{
int currentleft = FileText.Length-(16*count);
if(currentleft>16)
{
array[count]=FileText.Substring(i,16);
}
if(currentleft<16)
{
array[count]=FileText.Substring(i,currentleft);
}
count++;
}
This is the new code and provide a TRUE leftovers handling. Tested in ideone
Hope it works
Try this one:
var testArray = "sdfsdfjshdfalkjsdfhalsdkfjhalsdkfjhasldkjfhasldkfjhasdflkjhasdlfkjhasdlfkjhasdlfkjhasldfkjhalsjfdkhklahjsf";
var i = 0;
var query = from s in testArray
let num = i++
group s by num / 16 into g
select new {Value = new string(g.ToArray())};
var result = query.Select(x => x.Value).ToList();
result is List containing all the 16 char strings.

SubString editing

I've tried a few different methods and none of them work correctly so I'm just looking for someone to straight out show me how to do it . I want my application to read in a file based on an OpenFileDialog.
When the file is read in I want to go through it and and run this function which uses Linq to insert the data into my DB.
objSqlCommands.sqlCommandInsertorUpdate
However I want to go through the string , counting the number of ","'s found . when the number reaches four I want to only take the characters encountered until the next "," and do this until the end of the file .. can someone show me how to do this ?
Based on the answers given here my code now looks like this
string fileText = File.ReadAllText(ofd.FileName).Replace(Environment.NewLine, ",");
int counter = 0;
int idx = 0;
List<string> foo = new List<string>();
foreach (char c in fileText.ToArray())
{
idx++;
if (c == ',')
{
counter++;
}
if (counter == 4)
{
string x = fileText.Substring(idx);
foo.Add(fileText.Substring(idx, x.IndexOf(',')));
counter = 0;
}
}
foreach (string s in foo)
{
objSqlCommands.sqlCommandInsertorUpdate("INSERT", s);//laClient[0]);
}
However I am getting an "length cannot be less than 0" error on the foo.add function call , any ideas ?
A Somewhat hacky example. You would pass this the entire text from your file as a single string.
string str = "1,2,3,4,i am some text,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20";
int counter = 0;
int idx = 0;
List<string> foo = new List<string>();
foreach (char c in str.ToArray())
{
idx++;
if (c == ',')
{
counter++;
}
if (counter == 4)
{
string x = str.Substring(idx);
foo.Add(str.Substring(idx, x.IndexOf(',')));
counter = 0;
}
}
foreach(string s in foo)
{
Console.WriteLine(s);
}
Console.Read();
Prints:
i am some text
9
13
17
As Raidri indicates in his answer, String.Split is definitely your friend. To catch every fifth word, you could try something like this (not tested):
string fileText = File.ReadAllText(OpenDialog.FileName).Replace(Environment.NewLine, ",");
string words[] = fileText.Split(',');
List<string> everFifthWord = new List<string>();
for (int i = 4; i <= words.Length - 1, i + 5)
{
everyFifthWord.Add(words[i]);
}
The above code reads the selected file from the OpenFileDialog, then replaces every newline with a ",". Then it splits the string on ",", and starting with the fifth word takes every fifth word in the string and adds it to the list.
File.ReadAllText reads a text file to a string and Split turns that string into an array seperated at the commas:
File.ReadAllText(OpenDialog.FileName).Split(',')[4]
If you have more than one line use:
File.ReadAllLines(OpenDialog.FileName).Select(l => l.Split(',')[4])
This gives an IEnumerable<string> where each string contains the wanted part from one line of the file
It's not clear to me if you're after every fifth piece of text between the commas or if there are multiple lines and you want only the fifth piece of text on each line. So I've done both.
Every fifth piece of text:
var text = "1,2,3,4,i am some text,6,7,8,9"
+ ",10,11,12,13,14,15,16,17,18,19,20";
var everyFifth =
text
.Split(',')
.Where((x, n) => n % 5 == 4);
Only the fifth piece of text on each line:
var lines = new []
{
"1,2,3,4,i am some text,6,7",
"8,9,10,11,12,13,14,15",
"16,17,18,19,20",
};
var fifthOnEachLine =
lines
.Select(x => x.Split(',')[4]);

Categories

Resources