I'm new to programming in c# and I'm trying to figure out how I could
potentially reverse all words except words containing e in a string.
my current code will detect words containing e, and just writes them down in another textbox:
string text = txbInput.Text;
var words = text.Split(' ');
for (int i = 0; i < words.Length; i++)
{
if (words[i].Contains('e'))
{
txbOutput.Text += words[i];
}
Current:
Input: chicken crossing the road
Output: chickenthe
.
Expected outcome:
Input: chicken crossing the road
Output chicken gnissorc the daor
You can simply split the word on the space character, then, for each word, select either the word itself, or the word reversed (depending on whether or not it contains the 'e' character), and then join them back together again with the space character:
txbOutput.Text = string.Join(" ", txbInput.Text.Split(' ')
.Select(word => word.Contains("e") ? string.Concat(word.Reverse()) : word));
Outputs: chicken gnissorc the daor
using System;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
var input = "chicken crossing the road";
foreach (var item in input.Split(' '))
{
if (item.Contains('e'))
{
Console.Write(item + ' ');
}
else
{
Console.Write(Reverse(item) + ' ');
}
}
}
public static string Reverse(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
}
}
enter code here
EDIT
foreach (var item in input.Split(' '))
{
if (item.Contains('e'))
{
txbOutput.Text = txbOutput.Text+ item + ' ';
}
else
{
txbOutput.Text= txbOutput.Text+ Reverse(item) + ' ';
}
}
You can try using the following code -
string.Join(” “,
str.Split(‘ ‘)
.Select(x => new String(x.Reverse().ToArray()))
.ToArray());
Copied from - https://www.declarecode.com/code-solutions/csharp/caprogramtoreverseeachwordinthegivenstring
Related
I have 2 strings. I ut each charcter into a list using a foreach loop. I then use a for loop to go through each character in the 2 lists to see if there is a difference. Once I find a difference between the strings I want to find the start and end of that word that has changed eg. String1 is different to String2 I want the output to be "String1 String2 is the first second string". I plan on finding the start and end of the changed word using indexOf and at the moment it's not finding the position of the index.
static void Main(string[] args)
{
const string a = "String1 is the first string";
const string b = "String2 is the second string";
List<String> listString1 = new List<string>();
List<String> listString2 = new List<string>();
foreach (var item in a)
{
listString1.Add(item.ToString());
}
foreach (var item in b)
{
listString2.Add(item.ToString());
}
for (int i = 0; i < a.Length; i++)
{
var or = listString1[i];
var ed = listString2[i];
int nextSpace = or.IndexOf(' ', index);
int previousSpace = or.LastIndexOf(' ', index);
if (or!=ed)
{
Console.WriteLine();
}
}
}
Honestly, I am confused about what you're trying to achieve. But maybe I am on the right path with what I am providing.
static void Main(string[] args)
{
string firstString = "I am the first string";
string secondString = "I am the second string";
char delimiter = Convert.ToChar(" ");
if (firstString.Equals(secondString))
{
Console.WriteLine("Both strings are equal");
Console.ReadLine();
}
else
{
var firstStringList = firstString.Split(delimiter).ToList();
// ["I", "am", "the", "first", "string"]
var secondStringList = secondString.Split(delimiter).ToList();
// ["I", "am", "the", "second", "string"]
foreach (var word in firstStringList)
{
if (secondStringList.IndexOf(word) == -1)
{
var indexOfWord = firstStringList.IndexOf(word); // 3
secondStringList.Insert(indexOfWord, word); // Insert the word that was not found at position 3 inside secondStringList
// ["I", "am", "the", "first", "second", "string"]
// [ 0, 1, 2, 3, 4, 5 ]
Console.WriteLine(string.Join(" ", secondStringList));
// Join the secondStringList to make 1 string separated by the space character
Console.ReadLine();
}
}
}
}
This code will split the first string & second string into lists of strings containing the words that make up the strings.. then will loop through the first string list and compare each word within that list to the words in the second string list.. once it finds the word in the first string that does not exist in the second string.. it will print that word.
Again, not sure of the goal of this, but let me know based on what I posted what needs to be tailored.
Basic happy-path solution..
string newString = "";
string[] as1 = "String1 is the first string".Split(new char[] { ' ' });
string[] as2 = "String2 is the second string".Split(new char[] { ' ' });
for (int ndx = 0; ndx < as1.Length; ndx++)
{
newString += (as1[ndx] == as2[ndx]) ? as1[ndx] : as1[ndx] + ' ' + as2[ndx];
newString += ' ';
}
You need bounds checking on the arrays at least. But I'm not going to do all your homework for you :)
I am developing a Xamarin.Forms application on UWP
I have an Editor control - Basically a multi-line TextBox
I am trying to apply some simple grammatical casing to the string basically the following:
Capitalise the word "I"
Capitalise the First word
Capitalise the First word after a full stop.
I have managed to do the first two, and am a bit stuck on the third and was wondering if there is an easier way or whether my algorithm can be adapted.
What I have so far is:
public static string ToGramaticalCase(this string s)
{
var thingsToCapitalise = new String[] {"i"};
string newString = string.Empty;
if (!string.IsNullOrEmpty(s))
{
var wordSplit = s.Split(' ');
if (wordSplit.Count() > 1)
{
var wordToCapitalise = wordSplit.First();
wordToCapitalise = wordToCapitalise.Substring(0, 1).ToUpper() + wordToCapitalise.Substring(1);
var value = wordToCapitalise + s.Substring(wordToCapitalise.Length);
foreach (var item in thingsToCapitalise)
{
value = value.Replace(string.Format(" {0} ", item), string.Format(" {0} ", item.ToUpper()));
}
newString = value;
}
}
return newString;
}
This method will capitalize all words after ". ":
[Test]
public void Test()
{
var result = NewSentenceWithUpperLetter("Sentence one. sentence two.");
// result will be 'Sentence one. Sentence two.'
}
private string NewSentenceWithUpperLetter(string text)
{
var splitted = text.Split(' ');
for (var i = 1; i < splitted.Length; i++)
{
if (splitted[i - 1].EndsWith("."))
{
splitted[i] = splitted[i][0].ToString().ToUpper() + splitted[i].Substring(1);
}
}
return string.Join(" ", splitted);
}
Just split the string also on full stop. Change this line:
var wordSplit = s.Split(' ');
Into this:
var wordSplit = s.Split(new char[] { ' ', '.' },StringSplitOptions.RemoveEmptyEntries);
Edit
This extension method would do what you want:
public static string ToTitleCase(this string input)
{
string output =
String.Join(" ", input.Split(new char[] { ' ' },StringSplitOptions.RemoveEmptyEntries)
.ToList()
.Select(x => x = x.Length>1?
x.First().ToString().ToUpper() + x.Substring(1):
x.First().ToString().ToUpper()));
output =
String.Join(".", output.Split(new char[] { '.' },StringSplitOptions.RemoveEmptyEntries)
.ToList()
.Select(x => x = x.Length > 1 ?
x.First().ToString().ToUpper() + x.Substring(1) :
x.First().ToString().ToUpper()));
return output;
}
Test string: string input = "i try this test sentence .now it works as i want";
Output: I Try This Test Sentence .Now It Works As I Want
I am making a program to convert English to PigLatin. However, my solution only seems to work with one word. If I enter in more than ond word, only the last is translated.
testing one translation
Would simply output:
translationway
I've looked at some solutions, but most are in the same fashion as mine, or use "simplified" solutions beyond the scope of my knowledge.
Code:
static void Main(string[] args)
{
Console.WriteLine("Enter a sentence to convert to PigLatin:");
string sentence = Console.ReadLine();
string pigLatin = ToPigLatin(sentence);
Console.WriteLine(pigLatin);
}
static string ToPigLatin (string sentence)
{
string firstLetter,
restOfWord,
vowels = "AEIOUaeio";
int currentLetter;
foreach (string word in sentence.Split())
{
firstLetter = sentence.Substring(0, 1);
restOfWord = sentence.Substring(1, sentence.Length - 1);
currentLetter = vowels.IndexOf(firstLetter);
if (currentLetter == -1)
{
sentence = restOfWord + firstLetter + "ay";
}
else
{
sentence = word + "way";
}
}
return sentence;
All help is greatly appreciated!
Edit
Thanks to great feedback, I've updated my code:
static string ToPigLatin (string sentence)
{
const string vowels = "AEIOUaeio";
List<string> pigWords = new List<string>();
foreach (string word in sentence.Split(' '))
{
string firstLetter = word.Substring(0, 1);
string restOfWord = word.Substring(1, word.Length - 1);
int currentLetter = vowels.IndexOf(firstLetter);
if (currentLetter == -1)
{
pigWords.Add(restOfWord + firstLetter + "ay");
}
else
{
pigWords.Add(word + "way");
}
}
return string.Join(" ", pigWords);
}
Would it be very complex to adapt this code to work with consonant clusters?
For example, right now testing one translation prints as:
estingtay oneway ranslationtay
While, as I understand PigLatin rules, it should read:
estingtay oneway anslationtray
Just place += instead of = here:
if (currentLetter == -1)
{
sentence += restOfWord + firstLetter + "ay";
}
else
{
sentence += word + "way";
}
On your version, you were overriding the sentence in each iteration of your loop
Edit
I've made a lot of changes to the code:
public static string ToPigLatin(string sentence)
{
const string vowels = "AEIOUaeio";
List<string> newWords = new List<string>();
foreach (string word in sentence.Split(' '))
{
string firstLetter = word.Substring(0, 1);
string restOfWord = word.Substring(1, word.Length - 1);
int currentLetter = vowels.IndexOf(firstLetter);
if (currentLetter == -1)
{
newWords.Add(restOfWord + firstLetter + "ay");
}
else
{
newWords.Add(word + "way");
}
}
return string.Join(" ", newWords);
}
As Panagiotis-Kanavos said, and he's damn right, don't build your output on your input but with your input. Thus, I added the newWords list (some might prefer a StringBuilder, I don't).
You were misusing your variable in your loop, especially with the Substrings calls, it's now fixed.
If you have any question on this, don't hesitate.
private static void Main(string[] args)
{
Console.WriteLine("Enter a sentence to convert to PigLatin:");
string sentence = Console.ReadLine();
var pigLatin = GetSentenceInPigLatin(sentence);
Console.WriteLine(pigLatin);
Console.ReadLine();
}
private static string GetSentenceInPigLatin(string sentence)
{
const string vowels = "AEIOUaeio";
var returnSentence = "";
foreach (var word in sentence.Split())
{
var firstLetter = word.Substring(0, 1);
var restOfWord = word.Substring(1, word.Length - 1);
var currentLetter = vowels.IndexOf(firstLetter, StringComparison.Ordinal);
if (currentLetter == -1)
{
returnSentence += restOfWord + firstLetter + "ay ";
}
else
{
returnSentence += word + "way ";
}
}
return returnSentence;
}
I came up with a short LINQ implementation for this:
string.Join(" ", "testing one translation".Split(' ')
.Select(word => "aeiouy".Contains(word[0])
? word.Skip(1).Concat(word.Take(1))
: word.ToCharArray())
.Select(word => word.Concat("way".ToCharArray()))
.Select(word => string.Concat(word)));
Output: "testingway neoway translationway"
Of course, I'd probably refactor it to something like this:
"testing one translation"
.Split(' ')
.Select(word => word.ToCharsWithStartingVowelLast())
.Select(word => word.WithEnding("way"))
.Select(word => string.Concat(word))
.Join(' ');
static class Extensions {
public static IEnumerable<char> ToCharsWithStartingVowelLast(this string word)
{
return "aeiouy".Contains(word[0])
? word.Skip(1).Concat(word.Take(1))
: word.ToCharArray();
}
public static IEnumerable<char> WithEnding(this IEnumerable<char> word, string ending)
{
return word.Concat(ending.ToCharArray())
}
public static string Join(this IEnumerable<IEnumerable<char>> words, char separator)
{
return string.Join(separator, words.Select(word => string.Concat(word)));
}
}
Update:
With your edit, you asked about consonant clusters. One of the things I like about doing this with LINQ is that it's pretty simple to just update that part of the pipeline, and make it all work:
public static IEnumerable<char> ToCharsWithStartingConsonantsLast(this string word)
{
return word.SkipWhile(c => c.IsConsonant()).Concat(word.TakeWhile(c => c.IsConsonant()));
}
public static bool IsConsonant(this char c)
{
return !"aeiouy".Contains(c);
}
The entire pipeline, without refactoring to extension methods, now looks like this:
string.Join(" ", "testing one translation".Split(' ')
.Select(word => word.SkipWhile(c => !"aeiouy".Contains(c)).Concat(word.TakeWhile(c => !"aeiou".Contains(c))))
.Select(word => word.Concat("way".ToCharArray()))
.Select(word => string.Concat(word)))
and outputs "estingtway oneway anslationtrway".
Update 2:
I noticed I wasn't handling word endings correctly. Here's an update that takes care of only adding w to the ending when the word (without the ending) ends with a vowel:
string.Join(" ", "testing one translation".Split(' ')
.Select(word => word.SkipWhile(c => !"aeiouy".Contains(c)).Concat(word.TakeWhile(c => !"aeiou".Contains(c))))
.Select(word =>
{
var ending = "aeiouy".Contains(word.Last()) ? "way" : "ay";
return word.Concat(ending.ToCharArray());
})
.Select(word => string.Concat(word)))
Output: "estingtay oneway anslationtray". Note how it's only the step that handles adding the ending that changed - all other parts of the algorithm were unchanged.
Given how simple this now is, I'd probably only use two extension methods: Join(this IEnumerable<IEnumerable<char>> words, char separator) and IsConsonant(this char c) (the implementation of the latter should be easy given the code samples above). This yields the following final implementation:
"testing one translation"
.Split(' ')
.Select(word => word.SkipWhile(c => !c.IsVowel()).Concat(word.TakeWhile(c => c.IsVowel())))
.Select(word => word.Concat((word.Last().IsVowel() ? "way" : "ay").ToCharArray()))
.Select(word => string.Concat(word))
.Join(" ")
It's also really easy to see here what we do to translate:
Split the sentence into words
Shuffle any consonants to the end of the word (it's admittedly not apparent at first sight that this is what happens, but I can't find a simpler way to express it except by wrapping it in an extension method)
Add the ending
Convert IEnumerable<char>s to strings
Re-join the words into a sentence
How can I split string (from a textbox) by commas excluding those in double quotation marks (without getting rid of the quotation marks), along with other possible punctuation marks (e.g. ' . ' ' ; ' ' - ')?
E.g. If someone entered the following into the textbox:
apple, orange, "baboons, cows", rainbow, "unicorns, gummy bears"
How can I split the above string into the following (say, into a List)?
apple
orange
"baboons, cows"
rainbow
"Unicorns, gummy bears..."
Thank you for your help!
You could try the below regex which uses positive lookahead,
string value = #"apple, orange, ""baboons, cows"", rainbow, ""unicorns, gummy bears""";
string[] lines = Regex.Split(value, #", (?=(?:""[^""]*?(?: [^""]*)*))|, (?=[^"",]+(?:,|$))");
foreach (string line in lines) {
Console.WriteLine(line);
}
Output:
apple
orange
"baboons, cows"
rainbow
"unicorns, gummy bears"
IDEONE
Try this:
Regex str = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled);
foreach (Match m in str.Matches(input))
{
Console.WriteLine(m.Value.TrimStart(','));
}
You may also try to look at FileHelpers
Much like a CSV parser, instead of Regex, you can loop through each character, like so:
public List<string> ItemStringToList(string inputString)
{
var itemList = new List<string>();
var currentIem = "";
var quotesOpen = false;
for (int i = 0; i < inputString.Length; i++)
{
if (inputString[i] == '"')
{
quotesOpen = !quotesOpen;
continue;
}
if (inputString[i] == ',' && !quotesOpen)
{
itemList.Add(currentIem);
currentIem = "";
continue;
}
if (currentIem == "" && inputString[i] == ' ') continue;
currentIem += inputString[i];
}
if (currentIem != "") itemList.Add(currentIem);
return itemList;
}
Example test usage:
var test1 = ItemStringToList("one, two, three");
var test2 = ItemStringToList("one, \"two\", three");
var test3 = ItemStringToList("one, \"two, three\"");
var test4 = ItemStringToList("one, \"two, three\", four, \"five six\", seven");
var test5 = ItemStringToList("one, \"two, three\", four, \"five six\", seven");
var test6 = ItemStringToList("one, \"two, three\", four, \"five six, seven\"");
var test7 = ItemStringToList("\"one, two, three\", four, \"five six, seven\"");
You could change it to use StringBuilder if you want faster character joining.
Try with this it will work u c an split array string in many waysif you want to split by white space just put a space in (' ') .
namespace LINQExperiment1
{
class Program
{
static void Main(string[] args)
{
string[] sentence = new string[] { "apple", "orange", "baboons cows", " rainbow", "unicorns gummy bears" };
Console.WriteLine("option 1:"); Console.WriteLine("————-");
// option 1: Select returns three string[]’s with
// three strings in each.
IEnumerable<string[]> words1 =
sentence.Select(w => w.Split(' '));
// to get each word, we have to use two foreach loops
foreach (string[] segment in words1)
foreach (string word in segment)
Console.WriteLine(word);
Console.WriteLine();
Console.WriteLine("option 2:"); Console.WriteLine("————-");
// option 2: SelectMany returns nine strings
// (sub-iterates the Select result)
IEnumerable<string> words2 =
sentence.SelectMany(segment => segment.Split(','));
// with SelectMany we have every string individually
foreach (var word in words2)
Console.WriteLine(word);
// option 3: identical to Opt 2 above written using
// the Query Expression syntax (multiple froms)
IEnumerable<string> words3 =from segment in sentence
from word in segment.Split(' ')
select word;
}
}
}
This was trickier than I thought, a good practical problem I think.
Below is the solution I came up with for this. One thing I don't like about my solution is having to add double quotations back and the other one being names of the variables :p:
internal class Program
{
private static void Main(string[] args)
{
string searchString =
#"apple, orange, ""baboons, cows. dogs- hounds"", rainbow, ""unicorns, gummy bears"", abc, defghj";
char delimeter = ',';
char excludeSplittingWithin = '"';
string[] splittedByExcludeSplittingWithin = searchString.Split(excludeSplittingWithin);
List<string> splittedSearchString = new List<string>();
for (int i = 0; i < splittedByExcludeSplittingWithin.Length; i++)
{
if (i == 0 || splittedByExcludeSplittingWithin[i].StartsWith(delimeter.ToString()))
{
string[] splitttedByDelimeter = splittedByExcludeSplittingWithin[i].Split(delimeter);
for (int j = 0; j < splitttedByDelimeter.Length; j++)
{
splittedSearchString.Add(splitttedByDelimeter[j].Trim());
}
}
else
{
splittedSearchString.Add(excludeSplittingWithin + splittedByExcludeSplittingWithin[i] +
excludeSplittingWithin);
}
}
foreach (string s in splittedSearchString)
{
if (s.Trim() != string.Empty)
{
Console.WriteLine(s);
}
}
Console.ReadKey();
}
}
Another Regex solution:
private static IEnumerable<string> Parse(string input)
{
// if used frequently, should be instantiated with Compiled option
Regex regex = new Regex(#"(?<=^|,\s)(\""(?:[^\""]|\""\"")*\""|[^,\s]*)");
return regex.Matches(inputData).Where(m => m.Success);
}
I'm stuck on how to count how many words are in each sentence, an example of this is: string sentence = "hello how are you. I am good. that's good."
and have it come out like:
//sentence1: 4 words
//sentence2: 3 words
//sentence3: 2 words
I can get the number of sentences
public int GetNoOfWords(string s)
{
return s.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
label2.Text = (GetNoOfWords(sentance).ToString());
and i can get the number of words in the whole string
public int CountWord (string text)
{
int count = 0;
for (int i = 0; i < text.Length; i++)
{
if (text[i] != ' ')
{
if ((i + 1) == text.Length)
{
count++;
}
else
{
if(text[i + 1] == ' ')
{
count++;
}
}
}
}
return count;
}
then button1
int words = CountWord(sentance);
label4.Text = (words.ToString());
But I can't count how many words are in each sentence.
Instead of looping over the string as you do in CountWords I would just use;
int words = s.Split(' ').Length;
It's much more clean and simple. You split on white spaces which returns an array of all the words, the length of that array is the number of words in the string.
Why not use Split instead?
var sentences = "hello how are you. I am good. that's good.";
foreach (var sentence in sentences.TrimEnd('.').Split('.'))
Console.WriteLine(sentence.Trim().Split(' ').Count());
If you want number of words in each sentence, you need to
string s = "This is a sentence. Also this counts. This one is also a thing.";
string[] sentences = s.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
foreach(string sentence in sentences)
{
Console.WriteLine(sentence.Split(' ').Length + " words in sentence *" + sentence + "*");
}
Use CountWord on each element of the array returned by s.Split:
string sentence = "hello how are you. I am good. that's good.";
string[] words = sentence.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Length;
for (string sentence in sentences)
{
int noOfWordsInSentence = CountWord(sentence);
}
string text = "hello how are you. I am good. that's good.";
string[] sentences = s.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
IEnumerable<int> wordsPerSentence = sentences.Select(s => s.Trim().Split(' ').Length);
As noted in several answers here, look at String functions like Split, Trim, Replace, etc to get you going. All answers here will solve your simple example, but here are some sentences which they may fail to analyse correctly;
"Hello, how are you?" (no '.' to parse on)
"That apple costs $1.50." (a '.' used as a decimal)
"I like whitespace . "
"Word"
If you only need a count, I'd avoid Split() -- it takes up unnecessary space. Perhaps:
static int WordCount(string s)
{
int wordCount = 0;
for(int i = 0; i < s.Length - 1; i++)
if (Char.IsWhiteSpace(s[i]) && !Char.IsWhiteSpace(s[i + 1]) && i > 0)
wordCount++;
return ++wordCount;
}
public static void Main()
{
Console.WriteLine(WordCount(" H elloWor ld g ")); // prints "4"
}
It counts based on the number of spaces (1 space = 2 words). Consecutive spaces are ignored.
Does your spelling of sentence in:
int words = CountWord(sentance);
have anything to do with it?