Split string into array of words - c#

I want to split a string into an array of words without using string.Split. I tried already this code and it is working but cant assign the result into the array
string str = "Hello, how are you?";
string tmp = "";
int word_counter = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == ' ')
{
word_counter++;
}
}
string[] words = new string[word_counter+1];
for (int i = 0; i < str.Length; i++)
{
if (str[i] != ' ')
{
tmp = tmp + str[i];
continue;
}
// here is the problem, i cant assign every tmp in the array
for (int j = 0; j < words.Length; j++)
{
words[j] = tmp;
}
tmp = "";
}

You just need a kind of index pointer to put up your item one by one to the array:
string str = "Hello, how are you?";
string tmp = "";
int word_counter = 0;
for (int i = 0; i < str.Length; i++) {
if (str[i] == ' ') {
word_counter++;
}
}
string[] words = new string[word_counter + 1];
int currentWordNo = 0; //at this index pointer
for (int i = 0; i < str.Length; i++) {
if (str[i] != ' ') {
tmp = tmp + str[i];
continue;
}
words[currentWordNo++] = tmp; //change your loop to this
tmp = "";
}
words[currentWordNo++] = tmp; //do this for the last assignment
In my example the index pointer is named currentWordNo

Try using regular expressions, like this:
string str = "Hello, how are you?";
// words == ["Hello", "how", "are", "you"]
string[] words = Regex.Matches(str, "\\w+")
.OfType<Match>()
.Select(m => m.Value)
.ToArray();
String.Split is not a good option since there are too many characters to split on: ' ' (space), '.', ',', ';', '!' etc.
Word is not just a stuff between spaces, there are punctuations to consider, non-breaking spaces etc. Have a look at the input like this:
string str = "Bad(very bad) input to test. . ."
Note
Absence of space after "Bad"
Non-breaking space
Addition spaces after full stops
And the right output should be
["Bad", "very", "bad", "input", "to", "test"]

You can also use a List to create your words list:
string str = "Hello, how are you?";
string tmp = "";
List<string> ListOfWords = new List<string>();
int j = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] != ' ')
{
tmp = tmp + str[i];
continue;
}
// here is the problem, i cant assign every tmp in the array
ListOfWords.Add(tmp);
tmp = "";
}
ListOfWords.Add(tmp);
In this way you can avoid to count the number of word and the code is more simple. Use ListOfWord[x] to read any word

Related

How to remove spaces using IndexOf?

I created following to count number of words. Now I need to remove all spaces using IndexOf. I'm stuck. Can someone help? It has to be something simple, but I cant figure it out.
string text = "Hello. What time is it?";
int position = 0;
int noSpaces = 0;
for (int i = 0; i < text.Length; i++)
{
position = text.IndexOf(' ', position + 1);
if (position != -1)
{ noSpaces++; }
if (position == -1) break;
}
Console.WriteLine(noSpaces + 1);
If you are looking to just remove the spaces in your text so it would look like: Hello.Whattimeisit? then all you need to do is use String.Replace:
string text = "Hello. What time is it?";
string textWithNoSpaces = text.Replace(" ", "");
Console.WriteLine(textWithNoSpaces); // will print "Hello.Whattimeisit?"
If you are looking to split the text into separate words then you would want to use String.Split:
string text = "Hello. What time is it?";
string[] words = text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // "RemoveEmptyEntries" will remove any entries which are empty: ""
// words[0] > Hello.
// words[1] > What
// etc.
You then can get a count of how many words are in the text and then combine them, using String.Concat, if you need text in the form of Hello.Whattimeisit?:
int numberOfWords = words.Length;
string textWithNoSpaces = string.Concat(words);
Update: This is how you would count the number of words and remove spaces using String.IndexOf & String.Substring:
This is a really sloppy example, but it gets the job done
string text = "Hello. What time is it?";
string newText = string.Empty;
int prevIndex = 0;
int index1 = 0;
int index2 = 0;
int numberOfWords = 0;
while (true)
{
index1 = text.IndexOf(' ', prevIndex);
if (index1 == -1)
{
if (prevIndex < text.Length)
{
newText += text.Substring(prevIndex, (text.Length - prevIndex));
numberOfWords += 1;
}
break;
}
index2 = text.IndexOf(' ', (index1 + 1));
if ((index2 == -1) || (index2 > (index1 + 1)))
{
newText += text.Substring(prevIndex, (index1 - prevIndex));
numberOfWords += 1;
}
prevIndex = (index1 + 1);
}
Console.WriteLine(numberOfWords); // will print 5
Console.WriteLine(newText); // will print "Hello.Whattimeisit?"
Console.ReadLine();
If your requirement is to count the number of words, can't you try this?
string text = "Hello. What time is it?";
var arr = text.Split(' ');
var count = arr.Length;
.Net Fiddle
Strings are immutable so you cant achieve it with only IndexOf that will require multiple changes. if you need to achieve it with that particular method I think that StringBuilder is the only way. However if this is not some assignment and you plan to use it in real application I strongly dissuade because it is really process heavy.

Replacing words input by the user within a sentence and then outputting the sentence but with the censored/replaced words

I am aiming to replace words within an array (input by the user) that appear in a sentence. I want to then output this sentence but with the replace version which would be either ***** or for example censor would become c****r.
static void CensorSelectedWords(string _sentence, int _wordCount)
{
string[] words = new string[_wordCount];
string[] splitSentence = new string[_wordCount];
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Type in the words you wish to be censored: ");
words[i] = Console.ReadLine();
splitSentence = _sentence.Split(' ', '.', '?', ',', '!');
for (int j = 0; j < splitSentence.Length; j++)
if (splitSentence[j] == words[i])
splitSentence[j] = words[i].Replace(words[i], "*");
}
Console.WriteLine(splitSentence);
}
You can replace every word within _sentence like this:
static void CensorSelectedWords(string _sentence, int _wordCount)
{
string astr;
string[] words = new string[_wordCount];
string[] splitSentence = new string[_wordCount];
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Type in the words you wish to be censored: ");
words[i] = Console.ReadLine();
astr = "";
for (int j = 0; j < words[I].Length; j++)
astr += "*";
_sentence = _sentence.Replace(word[i], astr);
}
Console.WriteLine(_sentence);
}
I'm slightly confused at what the output should be, but here's one way to do it. I've extracted the functionality of replacing a word with censored text into separate function so it can be modified independently.
The rest is very simple - get a sentence, get a list of censored words, then replace all the words with their censored counterparts in the sentence and display it:
public static string HideAllButFirstAndLast(string word)
{
if (word == null) return null;
if (word.Length < 4) return new string('*', word.Length);
return word[0] + new string('*', word.Length - 2) + word[word.Length - 1];
}
private static void Main()
{
Console.WriteLine("Enter a sentence: ");
var sentence = Console.ReadLine();
Console.WriteLine("Enter a comma-separated list of censored words:");
var censoredWords = Console.ReadLine()
.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
.Select(word => word.Trim())
.ToList();
// Split sentence into words, replace words as needed, and join the words again
sentence = string.Join(" ", sentence.Split().Select(word =>
censoredWords.Contains(word, StringComparer.OrdinalIgnoreCase)
? HideAllButFirstAndLast(word)
: word));
Console.WriteLine(sentence);
GetKeyFromUser("\n\nDone! Press any key to exit...");
}
Output

how to split string into two strings when it finds a number

So basically if I have string a = "asd333"; I want to split this string into two strings
string b = "asd" and string c = "333"
for example string a = "aaa 555";string[]b = a.Split(' '); will make
b[0]="aaa" and b[1] = "555"
But this is not what i want i want to split string into two string withouth loosing characters and split it before a number
This is my code so far
string text = textBox4.Text.ToString();
char[] whitespace = new char[] { ' ','\t' };
string[] temp = text.Split(whitespace);
But i want to change it so string[] temp equals two string first is letters and second is numbers
I think it's not the best method, but it works
string a = "aaa333aaa333aaa22bb22bb1c1c1c";
List<string> result = new List<string>();
int lastSplitInedx = 0;
for (int i = 0; i < a.Length-1; i++)
{
if (char.IsLetter(a[i]) != char.IsLetter(a[i + 1]))
{
result.Add(a.Substring(lastSplitInedx, (i + 1) - lastSplitInedx));
lastSplitInedx = i+1;
}
if (i+1 == a.Length-1)
{
result.Add(a.Substring(lastSplitInedx));
}
}
foreach (string s in result)
{
Console.WriteLine(s);
}
Get the matched group from index 1 and 2.
String literals for use in programs:
C#
#"(\D+)\s*(\d+)"
Search for the integer in the string and split the string at that position
string a = "str123";
string b = string.Empty;
int val;
for (int i=0; i< a.Length; i++)
{
if (Char.IsDigit(a[i]))
b += a[i];
}
if (b.Length>0)
val = int.Parse(b);

Data from server split into a listbox

The data from server needs to be split into a ListBox. Below is my code.
private void button1_Click_2(object sender, EventArgs e)
{
//String[] arr = new String[1];
listBox1.Items.Clear();
listBox1.Items.Add("No Of Items=" + _server.Q.NoOfItem.ToString());
for (int i=0; i <= _server.Q.NoOfItem - 1; i++)
{
listBox1.Items.Add( _server.Q.ElementAtBuffer(i).ToString());
}
listBox2.Items.Add("No Of Items=" + _server.Q.NoOfItem.ToString());
for (int i = 0; i <= _server.Q.NoOfItem - 1; i++)
{
String words = _server.Q.ElementAtBuffer(i).ToString();
listBox2.Items.Add(words.Split(new char[] { '[' , ']', ' '}));
}
listBox1 should show all the data retrieved from the server. listBox2 is supposed to show data that has been split.
How can this be done?
This should work:
private void button1_Click_2(object sender, EventArgs e)
{
//String[] arr = new String[1];
listBox1.Items.Clear();
listBox1.Items.Add("No Of Items=" + _server.Q.NoOfItem.ToString());
for (int i=0; i <= _server.Q.NoOfItem - 1; i++)
{
listBox1.Items.Add( _server.Q.ElementAtBuffer(i).ToString());
}
String words = _server.Q.ElementAtBuffer(i).ToString();
listBox2.Items.Add("No Of Items=" + _server.Q.NoOfItem.ToString());
listBox2.Items.AddRange(words.Split(new char[] { '[' , ']', ' '}));
}
listBox1.Items.Clear();
listBox1.Items.Add("No Of Items=" + _server.Q.NoOfItem.ToString());
listBox2.Items.Add("No Of Items=" + _server.Q.NoOfItem.ToString());
for (int i = 0; i <= _server.Q.NoOfItem - 1; i++)
{
listBox1.Items.Add(_server.Q.ElementAtBuffer(i).ToString());
String words = _server.Q.ElementAtBuffer(i).ToString();
string[] arr = words.Split(new char[] { '[', ']', ' ' });
foreach (string word in arr)
listBox2.Items.Add(word);
}
Have your tried using Regex:
var pattern = #"\[(.*?)\]";
var matches = Regex.Matches(words, pattern);
foreach (Match m in matches)
{
listBox2.Items.Add(/* Add matched item */);
}
string[] strArray = words.Split(new char[] { '[' , ']', ' '})
for(int x = 0; x < strArray.Count; x++)
{listBox2.Items.Add(strArray[x]}
I guess you want to split words and add listboxs 2

interview question - how to loop through an array with a different starting point?

Let's say you have the string "This is a test"
I pass it to method zee, like ("This is a test", 1)
and want "test This is a";
I pass it to method zee, like ("This is a test", 2)
and want "a test This is";
the number can exceed the total words in variable. If it does it should loop around.
I started with....
public static string zee(string origString, int i)
{
StringBuilder sb = new StringBuilder();
ArrayList list = new ArrayList();
list.AddRange(origString.Split(' '));
// not sure here -
for (int c = i; c < (list.Count + i); c++)
{
sb.AppendFormat("{0} ", list[c]);
}
return sb.ToString();
}
for(int j=0; j < list.length; j++){
int idx = (j + i) % list.length;
sb.AppendFormat("{0} " , list[idx]);
}
Mostly like Brent Arias's solution, but I think a for loop is more readable, less likely to go infinite.
public static string zee(string origString, int i)
{
StringBuilder sb = new StringBuilder();
List<string> list = new List<string>();
list.AddRange(origString.Split(' '));
for (int j = 0; j < list.Count; j++)
{
int idx = (j + i) % list.Count;
sb.AppendFormat("{0} ", list[idx]);
}
return sb.ToString();
}
This is how I'd solve it.
private static string f(string s, int start)
{
var arr=s.Split(' ');
start %= arr.Length;
var res=arr.Skip(arr.Length - start).ToList();
res.AddRange(arr.Take(arr.Length - start));
return string.Join(" ", res);
}
I tried writing a one liner with linq but I don't see how to combine 2 lists. Union and Join aren't what I need.
This is how I'd solve it using strings.
public static string zee(string origString, int i)
{
string[] splitStr = origString.Split(' ');
string newStr = "";
// Not sure what you meant by wrap around but this should
// do the trick.
i %= splitStr.Length;
for (int j = (splitStr.Length - i); j < splitStr.Length; j++)
newStr += splitStr[j] + " "; // Add spaces taken by split :(
for (int j = 0; j < (splitStr.Length - i); j++)
newStr += splitStr[j] + " ";
return
newStr;
}
Here's an abomination trying to cram as much into one line as possible:
static string zee(string sentence, int wordCount)
{
var words = sentence.Split(' ');
return string.Join(" ", new[] { words.Skip(words.Count() - wordCount), words.Take(words.Count() - wordCount) }.SelectMany(w => w).ToArray());
}
I havn't tried it, but I think this would do it:
i %= list.Length;
int index = i;
do {
index %= list.Length;
sb.AppendFormat("{0} ", list[index]);
while (++index != i);
static string rearrange(string phase,int index)
{
string[] words = phase.Split(' ');
string[] newwords = new string[words.Length];
int pointer = index;
for (int i = 0; i < words.Length;i++ )
{
if(pointer>=words.Length)
{
pointer = 0;
}
newwords[i] = words[pointer];
pointer++;
}
return string.Join(" ", newwords);
}
Sounds like a homework question to me, but here is an efficient use of the .Net framework:
private static string [] SplitWords(string s, int startWord)
{
string[] words = s.Split(' ');
List<string> output = new List<string>();
output.AddRange(words.Skip(startWord).ToArray());
output.AddRange(words.Take(startWord).ToArray());
return output.ToArray();
}
There is absolutely no error checking in this function so you will have to modify it for production code but you get the idea.
public string SetStart(int startAt)
{
const string sentence = "this is a test so it is";
var words = sentence.Split(' ');
var x = (startAt > words.Count()) ? startAt%words.Count() : startAt;
return string.Join(" ", words.Skip(x).Concat(words.Take(x)));
}

Categories

Resources