Is there a way to remove characters from a current character array and then save it to a new character array. Following is the code:
string s1 = "move";
string s2 = "remove";
char[] c1 = s1.ToCharArray();
char[] c2 = s2.ToCharArray();
for (int i = 0; i < s2.Length; i++)
{
for (int p = 0; p < s1.Length; p++)
{
if (c2[i] == c1[p])
{
// REMOVE LETTER FROM C2
}
// IN THE END I SHOULD JUST HAVE c3 = re (ALL THE MATCHING CHARACTERS M-O-V-E SHOULD BE
DELETED)
Would appreciate your help
You can create a third array, c3, where you will add characters from c2 that are not to be removed.
You may also use Replace.
string s3 = s2.Replace(s1,"");
The original O(N^2) approach is wasteful. And I don't see how the other two answers actually perform the work you seem to be trying to accomplish. I hope this example, which has O(N) performance, works better for you:
string s1 = "move";
string s2 = "remove";
HashSet<char> excludeCharacters = new HashSet<char>(s1);
StringBuilder sb = new StringBuilder();
// Copy every character from the original string, except those to be excluded
foreach (char ch in s2)
{
if (!excludeCharacters.Contains(ch))
{
sb.Append(ch);
}
}
return sb.ToString();
Granted, for short strings the performance isn't likely to matter. But IMHO this is also easier to comprehend than the alternatives.
EDIT:
It is still not entirely clear to me what the OP is trying to do here. The most obvious task would be to remove whole words, but neither of his descriptions seem to say that's what he really wants. So, on the assumption that the above is not addressing his needs, but that he also does not want to remove whole words, here are a couple of other options...
1) O(N), the best approach for strings of non-trivial length, but is somewhat more complicated:
string s1 = "move";
string s2 = "remove";
Dictionary<char, int> excludeCharacters = new Dictionary<char, int>();
foreach (char ch in s1)
{
int count;
excludeCharacters.TryGetValue(ch, out count);
excludeCharacters[ch] = ++count;
}
StringBuilder sb = new StringBuilder();
foreach (char ch in s2)
{
int count;
if (!excludeCharacters.TryGetValue(ch, out count) || count == 0)
{
sb.Append(ch);
}
else
{
excludeCharacters[ch] = --count;
}
}
return sb.ToString();
2) An O(N^2) implementation which at least minimizes other unnecessary inefficiencies and which would suffice if all the inputs are relatively short:
StringBuilder sb = new StringBuilder(s2);
foreach (char ch in s1)
{
for (int i = 0; i < sb.Length; i++)
{
if (sb[i] == ch)
{
sb.Remove(i, 1);
break;
}
}
}
return sb.ToString();
This isn't particularly efficient, but it will probably be fast enough for short strings:
string s1 = "move";
string s2 = "remove";
foreach (char charToRemove in s1)
{
int index = s2.IndexOf(charToRemove);
if (index >= 0)
s2 = s2.Remove(index, 1);
}
// Result is now in s2.
Console.WriteLine(s2);
This avoids converting to a char array.
However, just to emphasize: This will be VERY slow for large strings.
[EDIT]
I have done some testing, and it turns out that this code is in fact pretty fast.
Here I'm comparing the code with the optimized code from another answer. However, note that we're not comparing entirely fairly, since the code here correctly implements the OP's requirement while the other code doesn't. However, it does demonstrate that the use of HashSet doesn't help as much as one might think.
I tested this code on a release build, not run inside a debugger (if you run it in a debugger, it does a debug build not a release build which will give incorrect timings).
This test uses target strings of length 1024 and chars to remove == "SKFPBPENAALDKOWJKFPOSKLW".
My results, where test1() is the incorrect but supposedly optimized solution from another answer, and test2() is my unoptimized but correct solution:
test1() took 00:00:00.2891665
test2() took 00:00:00.1004743
test1() took 00:00:00.2720192
test2() took 00:00:00.0993898
test1() took 00:00:00.2753971
test2() took 00:00:00.0997268
test1() took 00:00:00.2754325
test2() took 00:00:00.1026486
test1() took 00:00:00.2785548
test2() took 00:00:00.1039417
test1() took 00:00:00.2818029
test2() took 00:00:00.1029695
test1() took 00:00:00.2727377
test2() took 00:00:00.0995654
test1() took 00:00:00.2711982
test2() took 00:00:00.1009849
As you can see, test2() consistently outperforms test1(). This remains true even if the strings are increased to length 8192.
The test code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Demo
{
public static class Program
{
private static void Main(string[] args)
{
var sw = new Stopwatch();
string text = randomString(8192, 27367);
string charsToRemove = "SKFPBPENAALDKOWJKFPOSKLW";
int dummyLength = 0;
int iters = 10000;
for (int trial = 0; trial < 8; ++trial)
{
sw.Restart();
for (int i = 0; i < iters; ++i)
dummyLength += test1(text, charsToRemove).Length;
Console.WriteLine("test1() took " + sw.Elapsed);
sw.Restart();
for (int i = 0; i < iters; ++i)
dummyLength += test2(text, charsToRemove).Length;
Console.WriteLine("test2() took " + sw.Elapsed);
Console.WriteLine();
}
}
private static string randomString(int length, int seed)
{
var rng = new Random(seed);
var sb = new StringBuilder(length);
for (int i = 0; i < length; ++i)
sb.Append((char) rng.Next(65, 65 + 26*2));
return sb.ToString();
}
private static string test1(string text, string charsToRemove)
{
HashSet<char> excludeCharacters = new HashSet<char>(charsToRemove);
StringBuilder sb = new StringBuilder();
foreach (char ch in text)
{
if (!excludeCharacters.Contains(ch))
{
sb.Append(ch);
}
}
return sb.ToString();
}
private static string test2(string text, string charsToRemove)
{
foreach (char charToRemove in charsToRemove)
{
int index = text.IndexOf(charToRemove);
if (index >= 0)
text = text.Remove(index, 1);
}
return text;
}
}
}
[EDIT 2]
Here's a much more optimized solution:
public static string RemoveChars(string text, string charsToRemove)
{
char[] result = new char[text.Length];
char[] targets = charsToRemove.ToCharArray();
int n = 0;
int m = targets.Length;
foreach (char ch in text)
{
if (m == 0)
{
result[n++] = ch;
}
else
{
int index = findFirst(targets, ch, m);
if (index < 0)
{
result[n++] = ch;
}
else
{
if (m > 1)
{
--m;
targets[index] = targets[m];
}
else
{
m = 0;
}
}
}
}
return new string(result, 0, n);
}
private static int findFirst(char[] chars, char target, int n)
{
for (int i = 0; i < n; ++i)
if (chars[i] == target)
return i;
return -1;
}
Plugging that into my test program above shows that it runs around 3 times faster than test2().
Related
I need to find how many times the Anagrams are contained in a String like in this example:(the anagrams and the string itself)
Input 1(String) = thegodsanddogsweredogged
Input 2(String) = dog
Output(int) = 3
the output will be 3 because of these - (thegodsanddogsweredogged)
So far i managed to check how many times the word "dog" is contained in the string:
public ActionResult FindAnagram (string word1, string word2)
{
int ?count = Regex.Matches(word1, word2).Count;
return View(count);
}
This works to check how many times the word is contained but i still get an error: Cannot convert null to 'int' because it is a non-nulable value type.
So i need to check for how many times input 2 and the anagrams of input 2(dog,god,dgo,ogd etc) are contained in input 1?(int this case its 3 times-thegodsanddogsweredogged)
Thank you
I wanted to post a variation which is more readable at the cost of some runtime performance. Anton's answer is probably more performant, but IMHO less readable than it could be.
The nice thing about anagrams is that you know their exact length, and you can figure out all possible anagram locations quite easily. For a 3 letter anagram in a 100 letter haystack, you know that there are 98 possible locations:
0..2
1..3
2..4
...
96..98
97..99
These indexes can be generated quite easily:
var amountOfPossibleAnagramLocations = haystack.Length - needle.Length + 1;
var substringIndexes = Enumerable.Range(0, amountOfPossibleAnagramLocations);
At this point, you simply take every listed substring and test if it's an anagram.
var anagramLength = needle.Length;
int count = 0;
foreach(var index in substringIndexes)
{
var substring = haystack.Substring(index, anagramLength);
if(substring.IsAnagramOf(needle))
count++;
}
Note that a lot of this can be condensed into a single LINQ chain:
var amountOfPossibleAnagramLocations = haystack.Length - needle.Length + 1;
var anagramLength = needle.Length;
var anagramCount = Enumerable
.Range(0, amountOfPossibleAnagramLocations)
.Select(x => haystack.Substring(x, anagramLength))
.Count(substring => substring.IsAnagramOf(needle));
Whether it's more readable or not depends on how comfortable you are with LINQ. I personally prefer it (up to a reasonable size, of course).
To check for an anagram, simply sort the characters and check for equality. I used an extension method for the readability bonus:
public static bool IsAnagramOf(this string word1, string word2)
{
var word1Sorted = String.Concat(word1.OrderBy(c => c));
var word2Sorted = String.Concat(word2.OrderBy(c => c));
return word1Sorted == word2Sorted;
}
I've omitted things like case insensitivity or ignoring whitespace for the sake of brevity.
It would be better not to try to use Regex but write your own logic.
You can use a dictionary with key char - a letter of the word and value int - number of letter occurrences. And build such a dictionary for the word.
Anagrams will have similar dictionaries, so you can build a temp dictionary for each temp string built using the Windowing method over your str and compare it with the dictionary built for your word.
Here is my code:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var str = "thegodsanddogsweredogged";
var word = "dog";
Console.WriteLine("Word: " + word);
Console.WriteLine("Str: " + str);
Console.WriteLine();
var count = CountAnagrams(str, word);
Console.WriteLine("Count: " + count);
Console.ReadKey();
}
private static int CountAnagrams(string str, string word) {
var charDict = BuildCharDict(word);
int count = 0;
for (int i = 0; i < str.Length - word.Length + 1; i++) {
string tmp = "";
for (int j = i; j < str.Length; j++) {
tmp += str[j];
if (tmp.Length == word.Length)
break;
}
var tmpCharDict = BuildCharDict(tmp);
if (CharDictsEqual(charDict, tmpCharDict)) {
count++;
Console.WriteLine("Anagram: " + tmp);
Console.WriteLine("Index: " + i);
Console.WriteLine();
}
}
return count;
}
private static Dictionary<char, int> BuildCharDict(string word) {
var charDict = new Dictionary<char, int>();
foreach (var ch in word)
{
if (charDict.ContainsKey(ch))
{
charDict[ch] += 1;
}
else
{
charDict[ch] = 1;
}
}
return charDict;
}
private static bool CharDictsEqual(Dictionary<char, int> dict1, Dictionary<char, int> dict2)
{
if (dict1.Count != dict2.Count)
return false;
foreach (var kv in dict1) {
if (!dict2.TryGetValue(kv.Key, out var val) || val != kv.Value)
{
return false;
}
}
return true;
}
}
}
Possibly there is a better solution, but mine works.
P.S. About your error. You should change int? to int, because your View might expect non-nullable int type
I am doing this in this way but its remove string previous characters, its out put is (Magic,Agic,Gic,Ic,C) but I want the whole string to be concate before and after.
public string[] Transform(string st)
{
string[] arr = new string[st.Length];
string[] arr1 = new string[st.Length];
for (int x = 0; x < st.Length; x++)
{
arr1[x] = char.ToLower(st[x]) + "".ToString();
}
for (int i = 0; i < st.Length; i++)
{
string st1 = "";
{
st1 = char.ToUpper(st[i]) + st.Substring(i + 1);
}
arr[i] = st1;
}
return arr;
}
You can do this with a single loop:
public static string[] Transform(string str)
{
var strs = new List<string>();
var sb = new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
sb.Clear();
sb.Append(str);
sb[i] = char.ToUpper(str[i]);
strs.Add(sb.ToString());
}
return strs.ToArray();
}
What this does is adds the str to a StringBuilder and then modifies the indexed character with the upper case version of that character. For example, the input abcde will give:
Abcde
aBcde
abCde
abcDe
abcdE
Try it out on DotNetFiddle
If you wanted to get really fancy I'm sure there is some convoluted LINQ that can do the same, but this gives you a basic framework for how it can work.
You forgot to add left part of the string. Try to do like this:
st1 = st.ToLower().Substring + char.ToUpper(st[i]) + st.Substring(i + 1);
Here. This is twice as fast as the method that uses a string builder and a List
public static string[] Transform(string str)
{
var strs = new string [str.Length];
var sb = str.ToCharArray();
char oldCh;
for (int i = 0; i < str.Length; i++)
{
oldCh = sb[i];
sb[i] = char.ToUpper(sb[i]);
strs[i] = new string (sb);
sb[i] = oldCh;
}
return strs;
}
There's no need to clear and keep reading the string to the string builder. We also know the size of the array so that can be allocated at the start.
I wrote an answer for your questions (it's second code snippet), you can modify it for your needs, like changing the return type to string[], or use ToArray() extension method if you wanna stick with it. I think it's more readable this way.
I decided to put a the end little profiler to check CPU usage and memory compared to #Ron Beyer answer.
Here is my first attempt:
public static void Main()
{
var result = Transform("abcde");
result.ToList().ForEach(WriteLine);
}
public static IEnumerable<string> Transform(string str)
{
foreach (var w in str)
{
var split = str.Split(w);
yield return split[0] + char.ToUpper(w) + split[1];
}
}
Result:
Abcde
aBcde
abCde
abcDe
abcdE
Code fiddle https://dotnetfiddle.net/gnsAGX
There is one huge drawback of that code above, it works only if the passed word has unique letters. Therefore "aaaaa" won't produce proper result.
Here is my second successful attempt that seems works with any string input. I used one instance of StringBuilder to decrease the number of objects that would need to be created and manage on one instance, instead of so much copying objects so it's more optimized.
public static void Main()
{
var result = Transform("aaaaa");
result.ToList().ForEach(WriteLine);
}
public static IEnumerable<string> Transform(string str)
{
var result = new StringBuilder(str.ToLower());
for( int i = 0; i < str.Length; i++)
{
result[i] = char.ToUpper(str[i]);
yield return result.ToString();
result[i] = char.ToLower(str[i]);
}
}
Result:
Aaaaa
aAaaa
aaAaa
aaaAa
aaaaA
Code fiddle: https://dotnetfiddle.net/tzhXtP
Measuring execute time and memory uses.
I will use dotnetfiddle.net status panel, to make it easier.
Fiddle has few limitations like time execution of code 10 sec and used memory
besides differences are very significant.
I tested programs with 14 000 repetitions, my code additionally changes the output to array[].
My answer (https://dotnetfiddle.net/1fLVw9)
Last Run: 12:23:09 pm
Compile: 0.046s
Execute: 7.563s
Memory: 16.22Gb
CPU: 7.609s
Compared answer (https://dotnetfiddle.net/Zc88F2)
Compile: 0.031s
Execute: 9.953s
Memory: 16.22Gb
CPU: 9.938s
It slightly reduces the execution time.
Hope this helps!
public static string[] Transform(string str)
{
var strs = new string [str.Length];
var sb = str.ToCharArray();
char oldCh;
for (int i = 0; i < str.Length; i++)
{
oldCh = sb[i];
sb[i] = char.ToUpper(sb[i]);
strs[i] = new string (sb);
sb[i] = oldCh;
}
return strs;
}
This question already has answers here:
How would you count occurrences of a string (actually a char) within a string?
(34 answers)
Closed 6 years ago.
I need some help figure this one out. I need to search a string within a string and return the number of occurrences. I have tried the code below and it works and i also tried to use a regex and it worked but my teacher said to pretend that i can't use the indexOf or the regex. I know there have been some similar questions but that didn't help me much since they all use IndexOf or regex. So any ideas please?
What I have tried:
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
string s1 = "hellohjhghello";
string s2 = "he";
var r = Occurrences(s1, s2);
Console.WriteLine("{0} is repeated {1} times", s2, r);
}
static int Occurrences(string s1, string s2)
{
int count = 0;
int pos = 0;
while((pos = s1.IndexOf(s2,pos)) > -1)
{
count++;
pos += s2.Length;
}
return count;
}
}
}
EDIT:
I don't know what my teacher expects me to so but in another exercise I did a search for a char in string. He said to do something similar but for a string. My previous exercise goes like this:
class ex3
{
static void Main(string[] args)
{
string str = "aaabekldfj";
char letter = 'a';
var r = Occurrences(str, letter);
Console.WriteLine("The letter '{0}' from string '{1}' has {2} occurrences", letter, str,r);
}
static int Occurences(string str, char letter)
{
int repeat = 0;
for(int i=0; i< str.Length; i++)
{
if (str[i] == letter)
repeat++;
}
return repeat;
}
}
Why not keep it simple?
string compareText = "hello! This is a string to check hello's in this string!";
string compareWord = "hello";
int occurrences = (compareText.Length - compareText.Replace(compareWord, string.Empty).Length) / compareWord.Length;
Without indexof and regex and keeping it simple (but not fast), you can do following
static int OccurrencesAdvanced(string s1, string s2)
{
var result = 0;
for (var i = 0; i <= (s1.Length - s2.Length); i++)
{
var tested = s1.Substring(i, s2.Length);
if (string.Compare(tested, s2) == 0)
{
i += Math.Max(1, s2.Length - 1);
result++;
}
}
return result;
}
Here is my idea what first came in my mind. I don't know currently where are you in your studies so this solution might not good for you.
class Program
{
static void Main(string[] args)
{
var s1 = "hellohjhghello";
var s2 = "lo";
var occurence = 0;
Occurrences(s1, s2, ref occurence);
Console.WriteLine("{0} is repeated {1} times", s2, occurence);
Console.ReadLine();
}
static void Occurrences(string s1, string s2, ref int occurence)
{
var index = s1.IndexOf(s2);
if (index > -1)
{
occurence++;
s1 = s1.Substring(index + s2.Length);
Occurrences(s1, s2, ref occurence);
}
}
}
first time I write on the SO, because he could not find solution myself.
At the interview, I was given the task to write a method that checks the characters in the string to a unique.
Requirements: not using LINQ. Desirable: do not use additional data types (Dictionary, HashSet...etc. Arrays and lists Allowed)
Example:
"Hello" - return false; "Helo" - return true
My implementation:
static HashSet<char> charSet = new HashSet<char>();
static bool IsUniqueChar(string str)
{
foreach (char c in str)
{
charSet.Add(c);
}
return charSet.Count() == str.Length;
}
But it does not meet the requirements of data types, and is not the best performance...
I also tried the approach with a dictionary:
static Dictionary<char,bool> charSetDictionary = new Dictionary<char,bool>();
static bool IsUniqueChar(string str)
{
try
{
foreach (char c in str)
{
charSetDictionary.Add(c,true);
}
}
catch
{
return false;
}
But he is no better than the previous.
I will welcome any idea how to solve this task better?
p.s
static void Main(string[] args)
{
Stopwatch sw = Stopwatch.StartNew();
IsUniqueChar("Hello");
sw.Stop();
Console.WriteLine("Elapsed={0}", sw.Elapsed); //~005044
}
The fastest way uses HashSet<char>:
var set = new HashSet<char>();
foreach(var c in input)
{
if(!set.Add(c))
return false;
}
return true;
It's O(n) solution in worst case (input is unique). Returns false as soon as first duplicate is found.
Without HashSet<char> you can easily transform string to char[], sort it and check if you have two consecutive items with the same value.
var chars = input.ToCharArray();
chars.Sort();
for(int i = 1; i < chars.Length; i++)
{
if(chars[i-1] == chars[i])
return false;
}
return true;
Sort is O(n log(n)) and so is the entire function.
All answers so far are based on the assumption that one .NET char corresponds to one Unicode character. This is only true for characters in the Basic Multilingual Plane. Characters outside the BMP are encoded using two char objects (surrogate pair).
The following code handles this special case:
HashSet<string> set = new HashSet<string>();
for (int i = 0; i < str.Length; i++)
{
string s;
if (char.IsHighSurrogate(str[i]))
{
s = str.Substring(i, 2);
i++;
}
else
{
s = str.Substring(i, 1);
}
if (!set.Add(s))
{
return false;
}
}
return true;
Suppose the test string is passed through textBox1, then it follows:
string tst;
int i,j, stat =0;
tst = textBox1.Text;
for (i = 0; i < tst.Length; i++)
{
for (j = 0; j < tst.Length; j++)
{
if ((tst[i] == tst[j]) && (i != j))
{
stat = 1;
break;
}
else continue;
}
if (stat == 1) break;
else continue;
}
if (stat == 1) MessageBox.Show("False");
else MessageBox.Show("True");
Every string is an array of characters.
Most likely, your interviewer would like to see an approach using knowledge about Unicode:
static bool[] charsHash = new bool[512];
static bool IsUniqueChar(string str)
{
if (str.Length > 512) return false;
foreach (char c in str)
{
bool alreadyExist = charsHash[(int)c];
if (alreadyExist) return false;
else charsHash[(int)c] = !alreadyExist;
}
return true;
}
static void Main(string[] args)
{
Stopwatch sw = Stopwatch.StartNew();
IsUniqueChar("Hello");
sw.Stop();
Console.WriteLine("Elapsed={0}", sw.Elapsed);//~000283
}
I'm trying to count the number of words from a rich textbox in C# the code that I have below only works if it is a single line. How do I do this without relying on regex or any other special functions.
string whole_text = richTextBox1.Text;
string trimmed_text = whole_text.Trim();
string[] split_text = trimmed_text.Split(' ');
int space_count = 0;
string new_text = "";
foreach(string av in split_text)
{
if (av == "")
{
space_count++;
}
else
{
new_text = new_text + av + ",";
}
}
new_text = new_text.TrimEnd(',');
split_text = new_text.Split(',');
MessageBox.Show(split_text.Length.ToString ());
char[] delimiters = new char[] {' ', '\r', '\n' };
whole_text.Split(delimiters,StringSplitOptions.RemoveEmptyEntries).Length;
Since you are only interested in word count, and you don't care about individual words, String.Split could be avoided. String.Split is handy, but it unnecessarily generates a (potentially) large number of String objects, which in turn creates an unnecessary burden on the garbage collector. For each word in your text, a new String object needs to be instantiated, and then soon collected since you are not using it.
For a homework assignment, this may not matter, but if your text box contents change often and you do this calculation inside an event handler, it may be wiser to simply iterate through characters manually. If you really want to use String.Split, then go for a simpler version like Yonix recommended.
Otherwise, use an algorithm similar to this:
int wordCount = 0, index = 0;
// skip whitespace until first word
while (index < text.Length && char.IsWhiteSpace(text[index]))
index++;
while (index < text.Length)
{
// check if current char is part of a word
while (index < text.Length && !char.IsWhiteSpace(text[index]))
index++;
wordCount++;
// skip whitespace until next word
while (index < text.Length && char.IsWhiteSpace(text[index]))
index++;
}
This code should work better with cases where you have multiple spaces between each word, you can test the code online.
There are some better ways to do this, but in keeping with what you've got, try the following:
string whole_text = richTextBox1.Text;
string trimmed_text = whole_text.Trim();
// new line split here
string[] lines = trimmed_text.Split(Environment.NewLine.ToCharArray());
// don't need this here now...
//string[] split_text = trimmed_text.Split(' ');
int space_count = 0;
string new_text = "";
Now make two foreach loops. One for each line and one for counting words within the lines.
foreach (string line in lines)
{
// Modify the inner foreach to do the split on ' ' here
// instead of split_text
foreach (string av in line.Split(' '))
{
if (av == "")
{
space_count++;
}
else
{
new_text = new_text + av + ",";
}
}
}
new_text = new_text.TrimEnd(',');
// use lines here instead of split_text
lines = new_text.Split(',');
MessageBox.Show(lines.Length.ToString());
}
This was a phone screening interview question that I just took (by a large company located in CA who sells all kinds of devices that starts with a letter "i"), and I think I franked... after I got offline, I wrote this. I wish I were able to do it during interview..
static void Main(string[] args)
{
Debug.Assert(CountWords("Hello world") == 2);
Debug.Assert(CountWords(" Hello world") == 2);
Debug.Assert(CountWords("Hello world ") == 2);
Debug.Assert(CountWords("Hello world") == 2);
}
public static int CountWords(string test)
{
int count = 0;
bool wasInWord = false;
bool inWord = false;
for (int i = 0; i < test.Length; i++)
{
if (inWord)
{
wasInWord = true;
}
if (Char.IsWhiteSpace(test[i]))
{
if (wasInWord)
{
count++;
wasInWord = false;
}
inWord = false;
}
else
{
inWord = true;
}
}
// Check to see if we got out with seeing a word
if (wasInWord)
{
count++;
}
return count;
}
Have a look at the Lines property mentioned in #Jay Riggs comment, along with this overload of String.Split to make the code much simpler. Then the simplest approach would be to loop over each line in the Lines property, call String.Split on it, and add the length of the array it returns to a running count.
EDIT: Also, is there any reason you're using a RichTextBox instead of a TextBox with Multiline set to True?
I use an extension method for grabbing word count in a string. Do note, however, that double spaces will mess the count up.
public static int CountWords(this string line)
{
var wordCount = 0;
for (var i = 0; i < line.Length; i++)
if (line[i] == ' ' || i == line.Length - 1)
wordCount++;
return wordCount;
}
}
Your approach is on the right path. I would do something like, passing the text property of richTextBox1 into the method. This however won't be accurate if your rich textbox is formatting HTML, so you'll need to strip out any HTML tags prior to running the word count:
public static int CountWords(string s)
{
int c = 0;
for (int i = 1; i < s.Length; i++)
{
if (char.IsWhiteSpace(s[i - 1]) == true)
{
if (char.IsLetterOrDigit(s[i]) == true ||
char.IsPunctuation(s[i]))
{
c++;
}
}
}
if (s.Length > 2)
{
c++;
}
return c;
}
We used an adapted form of Yoshi's answer, where we fixed the bug where it would not count the last word in a string if there was no white-space after it:
public static int CountWords(string test)
{
int count = 0;
bool inWord = false;
foreach (char t in test)
{
if (char.IsWhiteSpace(t))
{
inWord = false;
}
else
{
if (!inWord) count++;
inWord = true;
}
}
return count;
}
using System.Collections;
using System;
class Program{
public static void Main(string[] args){
//Enter the value of n
int n = Convert.ToInt32(Console.ReadLine());
string[] s = new string[n];
ArrayList arr = new ArrayList();
//enter the elements
for(int i=0;i<n;i++){
s[i] = Console.ReadLine();
}
string str = "";
//Filter out duplicate values and store in arr
foreach(string i in s){
if(str.Contains(i)){
}else{
arr.Add(i);
}
str += i;
}
//Count the string with arr and s variables
foreach(string i in arr){
int count = 0;
foreach(string j in s){
if(i.Equals(j)){
count++;
}
}
Console.WriteLine(i+" - "+count);
}
}
}
int wordCount = 0;
bool previousLetterWasWhiteSpace = false;
foreach (char letter in keyword)
{
if (char.IsWhiteSpace(letter))
{
previousLetterWasWhiteSpace = true;
}
else
{
if (previousLetterWasWhiteSpace)
{
previousLetterWasWhiteSpace = false;
wordCount++;
}
}
}
public static int WordCount(string str)
{
int num=0;
bool wasInaWord=true;;
if (string.IsNullOrEmpty(str))
{
return num;
}
for (int i=0;i< str.Length;i++)
{
if (i!=0)
{
if (str[i]==' ' && str[i-1]!=' ')
{
num++;
wasInaWord=false;
}
}
if (str[i]!=' ')
{
wasInaWord=true;
}
}
if (wasInaWord)
{
num++;
}
return num;
}
class Program
{
static void Main(string[] args)
{
string str;
int i, wrd, l;
StringBuilder sb = new StringBuilder();
Console.Write("\n\nCount the total number of words in a string
:\n");
Console.Write("---------------------------------------------------
---\n");
Console.Write("Input the string : ");
str = Console.ReadLine();
l = 0;
wrd = 1;
foreach (var a in str)
{
sb.Append(a);
if (str[l] == ' ' || str[l] == '\n' || str[l] == '\t')
{
wrd++;
}
l++;
}
Console.WriteLine(sb.Replace(' ', '\n'));
Console.Write("Total number of words in the string is : {0}\n",
wrd);
Console.ReadLine();
}
This should work
input.Split(' ').ToList().Count;
This can show you the number of words in a line
string line = Console.ReadLine();
string[] word = line.Split(' ');
Console.WriteLine("Words " + word.Length);
You can also do it in this way!! Add this method to your extension methods.
public static int WordsCount(this string str)
{
return Regex.Matches(str, #"((\w+(\s?)))").Count;
}
And call it like this.
string someString = "Let me show how I do it!";
int wc = someString.WordsCount();