How to determine which line is longest by string in textbox - c#

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

Related

C# Array Different indexes

Hi i want to search for character in a string array but i need to search Between 2 indices. For example between index 2 and 10. How can I do that?
foreach (var item in currentline[2 to 10])
{
if (item == ',' || item == ';')
{
c++;
break;
}
else
{
data += item;
c++;
}
}
As you can see, foreach enumerates over a collection or any IEnumerable.
As the comments say, you can use a for loop instead, and pick out the elements you want.
Alternatively, since you want to search for a character in a string, you can use IndexOf, using the start index and count overload to find where a character is.
As there is no use of the c++ in your code I will assume that it's a vestige of code.
You can simply addess your issue like this:
In the currentline
Take char from index 2 to 10
Till you find a char you don't want.
concatenate the resulting char array to a string.
Resulting Code:
var data = "##";//01234567891 -- index for the string below.
var currentline= "kj[abcabc;z]Selected data will be between: '[]';";
var exceptChar = ",;";
data += new string(
input.Skip(3)
.Take(8)
.TakeWhile(x=> !exceptChar.Contains(x))
.ToArray()
);
There is a string method called string.IndexOfAny() which will allow you to pass an array of characters to search for, a start index and a count. For your example, you would use it like so:
string currentLine = ",;abcde;,abc";
int index = currentLine.IndexOfAny(new[] {',', ';'}, 2, 10-2);
Console.WriteLine(index);
Note that the last parameter is the count of characters to search starting at the specified index, so if you want to start at index 2 and finish at index 10, the count will be finish-start, i.e. 10-2.
You can search for characters in strings and get their indexes with this LINQ solution:
string str = "How; are, you; Good ,bye";
char[] charArr = { ',', ';' };
int startIndex = 2;
int endIndex = 10;
var indexes = Enumerable.Range(startIndex, endIndex - startIndex + 1)
.Where(i=>charArr.Contains(str[i]))
.ToArray();
In this case we get Enumerable.Range(2, 9) which generates a sequence between 2 and 10 and the Where clause filters the indexes of the characters in str that are matching one of the characters inside charArr.
Thanks everey one finaly i fixed it by your guid thanks all
myarr = new mytable[50];
number_of_records = 0;
number_of_records = fulllines.Length;
for (int line = 1; line < fulllines.Length; line++)
{
int c = 0;
for (int i = 0; i < record_lenth; i++)
{
string data = "";
string currentline = fulllines[line];
string value = "";
for (int x = c; x < fulllines[line].Length; x++)
{
value += currentline[x];
}
foreach (var item in value)
{
if (item == ',' || item == ';')
{
c++;
break;
}
else
{
data += item;
c++;
}
}
}
}

Having trouble finding the start of a sentence inside string array

I have a text file from which I read the text in lines. Also from all that text I need to find the longest sentence and find in which line it begins. I have no trouble finding the longest sentence but the problem arises when I need to find where it begins.
The contents of the text file is:
V. M. Putinas
Margi sakalai
Lydėdami gęstančią žarą vėlai
Pakilo į dangų;;, margi sakalai.
Paniekinę žemės vylingus sapnus,
Padangėje ištiesė,,; savo sparnus.
Ir tarė margieji: negrįšim į žemę,
Kol josios kalnai ir pakalnės aptemę.
My code:
static void Sakiniai (string fv, string skyrikliai)
{
char[] skyrikliaiSak = { '.', '!', '?' };
string naujas = "";
string[] lines = File.ReadAllLines(fv, Encoding.GetEncoding(1257));
foreach (string line in lines)
{
// Add lines into a string so I can separate them into sentences
naujas += line;
}
// Separating into sentences
string[] sakiniai = naujas.Split(skyrikliaiSak);
// This method finds the longest sentence
string ilgiausiasSak = RastiIlgiausiaSakini(sakiniai);
}
From the text file the longest sentence is: "Margi sakalai Lydėdami gęstančią žarą vėlai Pakilo į dangų;;, margi sakalai"
How can I find the exact line where the sentence begins?
What about a nested for loop? If two sentences are the same length, this just finds the first one.
var lines = File.ReadAllLines(fv, Encoding.GetEncoding(1257));
var terminators = new HashSet<char> { '.', '?', '!' };
var currentLength = 0;
var currentSentence = new StringBuilder();
var maxLength = 0;
var maxLine = default(int?);
var maxSentence = "";
for (var currentLine = 0; currentLine < lines.Count(); currentLine++)
{
foreach (var character in lines[currentLine])
{
if (terminators.Contains(character))
{
if (currentLength > maxLength)
{
maxLength = currentLength;
maxLine = currentLine;
maxSentence = currentSentence.ToString();
}
currentLength = 0;
currentSentence.Clear();
}
else
{
currentLength++;
currentSentence.Append(character);
}
}
}
First find the start index of the longest sentence in the whole content
int startIdx = naujas.IndexOf(ilgiausiasSak);
then loop the lines to find out which line the startIdx falls in
int i = 0;
while (i < lines.Length && startIdx >= 0)
{
startIdx -= lines[i].Length;
i++;
}
// do stuff with i
i is where the longest sentence starts at. e.g. i=2 means it start from the second line
Build an index that solves your problem.
We can make a straightforward modification of your existing code:
var lineOffsets = new List<int>();
lineOffsets.Add(0);
foreach (string line in lines)
{
// Add lines into a string so I can separate them into sentences
naujas += line;
lineOffsets.Add(naujas.Length);
}
All right; now you have a list of the character offset in your final string corresponding to each line.
You have a substring of the big string. You can use IndexOf to find the offset of the substring in the big string. Then you can search through the list to find the list index of the last element that is smaller or equal than the offset. That's the line number.
If the list is large, you can binary search it.
How about
identify the lines in the text
split the text into sentences
split the sentences into sections based on the line breaks (could work also with splitting on words as well if needed)
verify the sections of the sentence are on consecutive rows
In the end certain sections of the sentence might occur on multiple lines forming other sentences so you need to correctly identify the sentences spreading consecutive rows
// define separators for various contexts
var separator = new
{
Lines = new[] { '\n' },
Sentences = new[] { '.', '!', '?' },
Sections = new[] { '\n' },
};
// isolate the lines and their corresponding number
var lines = paragraph
.Split(separator.Lines, StringSplitOptions.RemoveEmptyEntries)
.Select((text, number) => new
{
Number = number += 1,
Text = text,
})
.ToList();
// isolate the sentences with corresponding sections and line numbers
var sentences = paragraph
.Split(separator.Sentences, StringSplitOptions.RemoveEmptyEntries)
.Select(sentence => sentence.Trim())
.Select(sentence => new
{
Text = sentence,
Length = sentence.Length,
Sections = sentence
.Split(separator.Sections)
.Select((section, index) => new
{
Index = index,
Text = section,
Lines = lines
.Where(line => line.Text.Contains(section))
.Select(line => line.Number)
})
.OrderBy(section => section.Index)
})
.OrderByDescending(p => p.Length)
.ToList();
// build the possible combinations of sections within a sentence
// and filter only those that are on consecutive lines
var results = from sentence in sentences
let occurences = sentence.Sections
.Select(p => p.Lines)
.Cartesian()
.Where(p => p.Consecutive())
.SelectMany(p => p)
select new
{
Text = sentence.Text,
Length = sentence.Length,
Lines = occurences,
};
and the end results would look like this
where .Cartesian and .Consecutive are just some helper extension methods over enumerable (see associated gist for the entire source code in linqpad ready format)
public static IEnumerable<T> Yield<T>(this T instance)
{
yield return instance;
}
public static IEnumerable<IEnumerable<T>> Cartesian<T>(this IEnumerable<IEnumerable<T>> instance)
{
var seed = Enumerable.Empty<T>().Yield();
return instance.Aggregate(seed, (accumulator, sequence) =>
{
var results = from vector in accumulator
from item in sequence
select vector.Concat(new[]
{
item
});
return results;
});
}
public static bool Consecutive(this IEnumerable<int> instance)
{
var distinct = instance.Distinct().ToList();
return distinct
.Zip(distinct.Skip(1), (a, b) => a + 1 == b)
.All(p => p);
}

Split string into multiple smaller strings

I have a multiline textbox that contains 10 digit mobile numbers separated by comma. I need to achieve string in group of at least 100 mobile numbers.
100 mobile numbers will be separated by 99 comma in total. What i am trying to code is to split the strings containing commas less than 100
public static IEnumerable<string> SplitByLength(this string str, int maxLength)
{
for (int index = 0; index < str.Length; index += maxLength) {
yield return str.Substring(index, Math.Min(maxLength, str.Length - index));
}
}
By using above code, I can achieve 100 numbers as 100 numbers will have 10*100(for mobile number)+99(for comma) text length. But the problem here is user may enter wrong mobile number like 9 digits or even 11 digits.
Can anyone guide me on how can I achieve this.
Thank you in advance.
You could use this extension method to put them into max-100 number groups:
public static IEnumerable<string[]> SplitByLength(this string str, string[] splitBy, StringSplitOptions options, int maxLength = int.MaxValue)
{
var allTokens = str.Split(splitBy, options);
for (int index = 0; index < allTokens.Length; index += maxLength)
{
int length = Math.Min(maxLength, allTokens.Length - index);
string[] part = new string[length];
Array.Copy(allTokens, index, part, 0, length);
yield return part;
}
}
Sample:
string text = string.Join(",", Enumerable.Range(0, 1111).Select(i => "123456789"));
var phoneNumbersIn100Groups = text.SplitByLength(new[] { "," }, StringSplitOptions.None, 100);
foreach (string[] part in phoneNumbersIn100Groups)
{
Assert.IsTrue(part.Length <= 100);
Console.WriteLine(String.Join("|", part));
}
You have a few options,
Put some kind of mask on the input data to prevent the user entering invalid data. In your UI you could then flag the error and prompt the user to reenter correct information. If you go down this route then something like this string[] nums = numbers.Split(','); will be fine.
Alternatively, you could use regex.split or regex.match and match on the pattern. Something like this should work assuming your numbers are in a string with a leading comma or space
Regex regex = new Regex("(\s|,)\d{10},)";
string[] nums = regex.Split(numbers);
This be can resolved with a simple Linq code
public static IEnumerable<string> SplitByLength(this string input, int groupSize)
{
// First split the input to the comma.
// this will give us an array of all single numbers
string[] numbers = input.Split(',');
// Now loop over this array in groupSize blocks
for (int index = 0; index < numbers.Length; index+=groupSize)
{
// Skip numbers from the starting position and
// take the following groupSize numbers,
// join them in a string comma separated and return
yield return string.Join(",", numbers.Skip(index).Take(groupSize));
}
}

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]);

String to array

I have a string :
id0:xxxxx:id0-value:xxxxx:id1:xxxxxxxx:id1-value:xxxxx:id3:xxxxxxxx:id3-value:xxx
I just need the value for idX-value from the string into array.
How can I achieve it?
The simple way, the value is in position (4x - 1):
var list = input.Split(':');
var outputs = new List<string>();
for (int index = 0; index < list.Count(); index++)
{
if (index % 4 == 3)
outputs.Add(list.ElementAt(index));
}
Use String.Split()
http://msdn.microsoft.com/en-us/library/system.string.split.aspx
String myString = "id0:xxxxx:id0-value:xxxxx:id1:xxxxxxxx:id1-value:xxxxx:id3:xxxxxxxx:id3-value:xxx";
String[] tokens = myString.Split(new Char[] {':'});
The token array will contain {"id0","xxxxx","id0-value","xxxxx","id1","xxxxxxxx","id1-value","xxxxx","id3","xxxxxxxx","d3-value","xxx"}
The second possibility is to use String.IndexOf() and String.Substring().
http://msdn.microsoft.com/en-us/library/5xkyx09y
http://msdn.microsoft.com/en-us/library/aka44szs
Int start = 0;
ArrayList tokens;
while((start = myString.IndexOf("-value:", start)) > -1) {
ArrayList.Add(myString.Substring(start+6, myString.IndexOf(":", start+7);
start += 6; // Jump past what we just found.
}
Split it using a Regex(a regex which splits : coming after x), then split using colon : and use first index as a Dictionary Key and Second index as Dictionary value.

Categories

Resources