I have a string variable called: Test
The content of Test is 150 lines.
I want to count each two lines and after this two lines to inser/add a new empty line to make space between each two lines.
So in index 3 to insert empty line in index 6 to insert empty line in index 9 ,12,15.
And when i get to the last line don't add after it an empty line. Only between each two lines. Not in the beginning and not in the end only between each two lines.
This is what i have: combindedString is single string variable:
string[] ss = combindedString.Split(new string[] { "\n", "\r\n" },
StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < ss.Length; i++)
ss[i] = ss[i].Trim();
combindedString = String.Join("\n", ss);
After that code which is also what i need in the end in combindedString it's content is like this:
I see many lines the first line is just text: hello world
Second line is date&time line: 6/16/2014...
Third line is another text: hello everyone
Fourth line is again date&time: 5/16/2014...
And so on all the lines are text and after it date&time.
I want after each text and date&time line to insert one empty space line.
So in the end the content in combindedString will look like:
Hello world
6/16/2014
Hi everyone
5/16/2014
This is test
5/16/2014
Instead of how it is now without the spaces. I want to add space between each two lines:
Hello world
6/16/2014
Hi everyone
5/16/2014
This is test
5/16/2014
To insert an empty/space line after each text and date&time lines.
You could do something like:
string[] lines = combindedString.Split(new string[] { "\n", "\r\n" },
StringSplitOptions.RemoveEmptyEntries);
var result = new StringBuilder();
for (int i = 0; i < lines.Length; i++)
{
if (i % 2 == 0 && i != 0) // i != 0 to not get blank line at the beginning
result.AppendLine();
result.AppendLine(lines[i].Trim());
}
combindedString = result.ToString();
See example HERE.
It is a lot easier using a List<string> instead of an array
string[] lines = new string[] {"1","2","3","4","5","6","7","8","9"};
List<string> copyList = lines.ToList();
for(int x = copyList.Count()- 1; x > 0; x--)
{
if(x % 2 == 0)
copyList.Insert(x, "");
}
string combinedString = string.Join(Environment.NewLine, copyList);
There is also the one line solution provided by Linq
string result = string.Join(Environment.NewLine,
lines.Select ((l,i) => (i % 2 == 1 ? l + Environment.NewLine : l)));
Here is a function that will add a line after every second line.
public string InsertLines(string Test)
{
var builder = new StringBuilder();
var lines = Test.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
for (var i = 0; i < lines.Length; ++i)
{
if (i != 0 && i % 2 == 0)
builder.AppendLine();
builder.AppendLine(lines[i]);
}
return builder.ToString();
}
This works:
var lookup = ss
.Concat(ss.Length % 2 == 0
? Enumerable.Empty<string>()
: new [] { "" })
.Select((x, n) => new { x, n })
.ToLookup(xn => xn.n % 2 == 0, xn => xn.x);
var query =
lookup[true]
.Zip(lookup[false], (o, e) => new [] { o, e, "" })
.SelectMany(x => x);
var result = String.Join(Environment.NewLine, query);
LINQ all the way. :-)
Related
I have created a simple page that contains plain text like this:
Line 1
Line 2
Line 3
Line 4
And I made a c# Winform app that contains a textbox
Textbox text is like
Line 1
Line 2
I want to check if a textbox line contains any of downloaded string from my website
here's what i tried but doesn't work
int pub = 0;
int priv = 0;
WebClient data = new WebClient();
string reply = data.DownloadString("http://mytoosupd.000webhostapp.com/public-keys.html");
for (int i=0; i < textBox1.Lines.Length; i++)
{
if (textBox1.Lines[i].Contains(reply + "\n"))
{
pub++;
label5.Text = pub.ToString();
continue;
}
else if (!textBox1.Lines[i].Contains(reply))
{
priv++;
label4.Text = priv.ToString();
}
}
Split, Intersect, Any would be easy enough
string reply = data.DownloadString(..);
var result = reply
.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.RemoveEmptyEntries)
.Intersect(textBox1.Lines)
.Any();
Debug.WriteLine($"Found = {result}");
Update
// to get a list of the intersected lines, call `ToList()` instead
var list = reply
.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.RemoveEmptyEntries)
.Intersect(textBox1.Lines)
.ToList();
// list.Count() to get the count
// use this list where ever you like
// someTextBox.Text = String.Join(Environment.NewLine, list);
// or potentially
// someTextBox.Lines = list.ToArray();
I've got a problem. I need to split my every string like this:
For example:
"Economic drive without restrictions"
I need array with sub string like that:
"Economic drive without"
"drive without restrictions"
For now i have this:
List<string> myStrings = new List<string>();
foreach(var text in INPUT_TEXT) //here is Economic drive without restrictions
{
myStrings.DefaultIfEmpty();
var textSplitted = text.Split(new char[] { ' ' });
int j = 0;
foreach(var textSplit in textSplitted)
{
int i = 0 + j;
string threeWords = "";
while(i != 3 + j)
{
if (i >= textSplitted.Count()) break;
threeWords = threeWords + " " + textSplitted[i];
i++;
}
myStrings.Add(threeWords);
j++;
}
}
You could use this LINQ query:
string text = "Economic drive without restrictions";
string[] words = text.Split();
List<string> myStrings = words
.Where((word, index) => index + 3 <= words.Length)
.Select((word, index) => String.Join(" ", words.Skip(index).Take(3)))
.ToList();
Because others commented that it would be better to show a loop version since OP is learning this language, here is a version that uses no LINQ at all:
List<string> myStrings = new List<string>();
for (int index = 0; index + 3 <= words.Length; index++)
{
string[] slice = new string[3];
Array.Copy(words, index, slice, 0, 3);
myStrings.Add(String.Join(" ", slice));
}
I try to give a simple solution. So i hope you can better understand it.
List<string> myStrings = new List<string>();
string input = "Economic drive without restrictions";
var allWords = input.Split(new char[] {' '});
for (int i = 0; i < allWords.Length - 2; i++)
{
var textSplitted = allWords.Skip(i).Take(3);
string threeString = string.Join(" ", textSplitted);
myStrings.Add(threeString);
}
foreach (var myString in myStrings)
{
Console.WriteLine(myString);
}
The method Take(n) is from Linq. It takes the first n elements of the given array. for example if you have an array a,b,c,d,e then Take(3) will give you a new array a,b,c.
The method Skip(n) is from Linq. It gives you the new array by skipping first n elements. given array a,b,c,d,e then Skip(1) will return b,c,d,e. as you can see it skipped the first elements.
Now with this two methods you can move on array 3 by 3 and get the words you want.
Just for comparative purposes, here's another solution that doesn't use Linq:
string[] words = INPUT_TEXT.Split();
List<string> myStrings = new List<string>();
for (int i = 0; i < words.Length - 2; ++i)
myStrings.Add(string.Join(" ", words[i], words[i+1], words[i+2]));
Or using ArraySegment<string>:
string[] words = INPUT_TEXT.Split();
List<string> myStrings = new List<string>();
for (int i = 0; i < words.Length - 2; ++i)
myStrings.Add(string.Join(" ", new ArraySegment<string>(words, i, 3)));
I would use one of the methods described here ; for instance the following that takes the elements 3 by 3.
var groups = myStrings.Select((p, index) => new {p,index})
.GroupBy(a =>a.index/3);
Warning, it is not the most memory efficient, if you start parsing big strings, it might blow up on you. Try and observe.
Then you only need to handle the last element. If it has less than 3 strings, fill it up from the left.
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]);
I have a text file that I load into a string array. The contents of the file looks something like this:
OTI*IA*IX*NA~ REF*G1*J EVERETTE~ REF*11*0113722462~
AMT*GW*229.8~ NM1*QC*1*JENNINGS*PHILLIP~ OTI*IA*IX*NA~ REF*G1*J
EVERETTE~ REF*11*0113722463~ AMT*GW*127.75~
NM1*QC*1*JENNINGS*PHILLIP~ OTI*IA*IX*NA~ REF*G1*J EVERETTE~
REF*11*0113722462~ AMT*GW*10.99~ NM1*QC*1*JENNINGS*PHILLIP~ ...
I'm looking for the lines that start with OTI, and if it's followed by "IA" then I need to get the 10 digit number from the line that starts with REF*11. So far, I have this:
string[] readText = File.ReadAllLines("myfile.txt");
foreach (string s in readText) //string contains 1 line of text from above example
{
string[] currentline = s.Split('*');
if (currentline[0] == "OTI")
{
//move down 2 lines and grab the 10 digit
//number from the line that starts with REF*11
}
}
The line I need is always 2 lines after the current OTI line. How do I access the line that's 2 lines down from my current line?
Instead of using foreach() you can use a for(int index = 0; index < readText.Length; index++)
Then you know the line you are accessing and you can easily say int otherIndex = index + 2
string[] readText = File.ReadAllLines("myfile.txt");
for(int index = 0; index < readText.Length; index++)
{
string[] currentline = readText[index].Split('*');
if (currentline[0] == "OTI")
{
//move down 2 lines and grab the 10 digit
//number from the line that starts with REF*11
int refIndex = index + 2;
string refLine = readText[refIndex];
}
}
What about:
string[] readText = File.ReadAllLines("myfile.txt");
for (int i = 0; i < readText.Length; i++)
{
if (readText[i].StartsWith("OTI") && readText[i+2].StartsWith("REF*11")){
string number = readText[i+2].Substring("REF*11".Length, 10);
//do something
}
}
This looks like an EDI file! Ahh, EDI, the memories...
The good news is that the EDI file is delimited, just like most CSV file formats. You can use any standard CSV file library to load the EDI file into a gigantic array, and then iterate through it by position.
I published my open source CSV library here, feel free to use it if it's helpful. You can simply specify the "asterisk" as the delimiter:
https://code.google.com/p/csharp-csv-reader/
// This code assumes the file is on disk, and the first row of the file
// has the names of the columns on it
DataTable dt = CSVReader.LoadDataTable(myfilename, '*', '\"');
At this point, you can iterate through the datatable as normal.
for (int i = 0; i < dt.Rows.Count; i++) {
if (dt.Rows[i][0] == "OTI") {
Console.WriteLine("The row I want is: " + dt.Rows[i + 2][0]);
}
}
If you want to use regex to tokenize the items and create dynamic entities, here is such a pattern
string data = #"NM1*QC*1*JENNINGS*PHILLIP~
OTI*IA*IX*NA~
REF*G1*J EVERETTE~
REF*11*0113722463~
AMT*GW*127.75~
NM1*QC*1*JENNINGS*PHILLIP~
OTI*IA*IX*NA~
REF*G1*J EVERETTE~
REF*11*0113722462~
AMT*GW*10.99~
NM1*QC*1*JENNINGS*PHILLIP~";
string pattern = #"^(?<Command>\w{3})((?:\*)(?<Value>[^~*]+))+";
var lines = Regex.Matches(data, pattern, RegexOptions.Multiline)
.OfType<Match>()
.Select (mt => new
{
Op = mt.Groups["Command"].Value,
Data = mt.Groups["Value"].Captures.OfType<Capture>().Select (c => c.Value)
}
);
That produces a list of items like this which you can apply your business logic to:
Why dont you use regular expression matches using Regex.Match or Regex.Matches defined in System.Text.RegularExpressions? You can also look at string pattern matching algorithms such as the Knuth-Morris-Pratt algorithms.
string[] readText = File.ReadAllLines("myfile.txt");
foreach (string s in readText) //string contains 1 line of text from above example
{
string[] currentline = s.Split('*');
if (currentline[0] == "REF"&¤tline[1] == "11")
{
found=false;
needed=current+2;
}
}
string[] readText = File.ReadAllLines("myfile.txt");
for(int linenum = 0;linenum < readText.Length; linenum++)
{
string s = readText[linenum];
string[] currentline = s.Split('*');
if (currentline[0] == "OTI")
{
//move down 2 lines and grab the 10 digit
linenum +=2;
string refLine = readText[linenum];
//number from the line that starts with REF*11
// Extract your number here from refline
}
}
Thank guys .. this is what I came up with, but I'm also reading your answers as I KNOW I will learn something! Thanks again!
string[] readText = File.ReadAllLines("myfile.txt");
int i = 0;
foreach (string s in readText)
{
string[] currentline = s.Split('*');
if (currentline[0] == "OTI")
{
lbRecon.Items.Add(readText[i+2].Substring(8, 9));
}
i++;
}
Input : 1 ; a ; 2; b; 3;c;4;d;5;e;6;f
output I'm getting : 1a ; a2;b3;c4;d5;e6
output I want: 1a ; 2b ; 3c; 4d ; 5e; 6f
I know this is a simple thing but I just can't seem to get my damn head around it....
Heres my code:
for (int x = 0; x < coll.Count; x++)
{
if (x == 0)
{
line.Append(coll[x].ToString());
line.AppendLine(coll[x + 1].ToString());
}
else
{
if (x % 2 == 0)
{
}
else
{
try
{
line.Append(coll[x].ToString());
line.AppendLine(coll[x + 1].ToString());
x++;
textBox1.Text = line.ToString();
}
catch { }
}
}
If you want to keep the code the way it is (I'm assuming something will go in the empty conditional), then you just need to change if (x % 2 == 0) to if (x % 2 != 0) (or equally if (x % 2 == 1)), as your code is currently appending to the line when i = 0, then 1, 3,... i.e. all odd numbered indices, whereas you need to be appending to the line at all even numbered indices.
(Unfortunately I can't edit your question, but if you just stick four spaces in front of the line starting with for then it should be formatted correctly.)
If your list is like = [1,a,2,b,3,c,4,d,5,e,6,f]
Try this;
String line = "";
for(int i=0;i<list.size();i+2){
line += list.get(i)+list.get(i+1);
}
textBox1.Text = line;
EDIT
And if you want semi colons;
I edited like
String line = "";
for(int i=0;i<list.size();i+2){
line += list.get(i)+list.get(i+1);
if(i != list.size() - 2){
line+=";";
}
}
textBox1.Text = line;
One line code with LINQ (but not so efficient):
string[] source = { "1", "a", "2", "b", "3", "c" };
var result = source.Zip(source.Skip(1), (s1, s2) => s1 + s2)
.Where((s, i) => i % 2 == 0);
string[] arrayResult = result.ToArray();
string stringResultWithSeperator = string.Join(";", result);
Another LINQy solution:
string input = "1;a;2;b;3;c;4;d;5;e;6;f";
var split = input.Split(';');
string rejoined = String.Join(";", Pairs(split));
Where Pairs is
IEnumerable<string> Pairs(IEnumerable<string> strings)
{
if (strings.Take(1).Count() == 0)
{
return new string[]{};
}
return new [] {String.Join("", strings.Take(2))}.Concat(Pairs(strings.Skip(2)));
}