Reversing a string sentence (not necessarily space between each) - c#

I have this string:
com.example.is-this#myname
i would like it to be
myname#this-is.example.com
using .Net, but a straight out concept or an idea would be good to.
What i'm currently doing is going over each character, find out if it's one of the "special characters" and assign all prior chars, to a variable of an array, at the end, i'm joining them all together from last to first.
is there a possible more efficient way to do this ?

This is the classic word-by-word reversal, with a small twist on delimiters. A solution to this problem is reversing each word individually, and then reversing the whole string. Do not touch delimiters when reversing words.
First step goes as follows: we find limits of each token, and reverse it in place, like this:
com.example.is-this#myname
moc.example.is-this#myname
moc.elpmaxe.is-this#myname
moc.elpmaxe.si-this#myname
moc.elpmaxe.si-siht#myname
moc.elpmaxe.si-siht#emanym
Reverse the result to get your desired output:
moc.elpmaxe.si-siht#emanym -> myname#this-is.example.com
As far as the implementation goes, you can do it by converting the string to an array of characters to make it changeable in place, and write a short helper method that lets you reverse a portion of a char array between indexes i and j. With this helper method in place, all you need to do is to find delimiters and call the helper for each delimited word, and then make one final call to reverse the entire sentence.

With little bit of Regex and Linq this is fairly simple.
Idea is that we take words and non word characters as separate token with Regex patten. Then, we just reverse it and join it.
var tokens = Regex.Matches("com.example.is-this#myname", #"\w+|\W")
.Cast<Match>()
.Select(x=>x.Value)
.Reverse();
string reversed = string.Concat(tokens);
Output: Ideone - Demo
myname#this-is.example.com

You could use the Split C# method.
The example below is from here.
using System;
class Program
{
static void Main()
{
string s = "there is a cat";
// Split string on spaces.
// ... This will separate all the words.
string[] words = s.Split(' ');
foreach (string word in words)
{
Console.WriteLine(word);
}
}
}
Is as simple as examples get.
Then you add more conditions to your Split()
string [] split = strings .Split(new Char [] {'.' , '#', '-' },
StringSplitOptions.RemoveEmptyEntries);
The RemoveEmptyEntries just removes unwanted empty entries to your array.
After that you reverse your array using the Array.Reverse method.
And then you can stitch your string back together with a Foreach loop.
As #marjan-venema mentioned in the comments you could populate a parallel array at this point with each delimiter. Reverse it, and then concatenate the string when you are using the Foreach loop at each entry.

Here's another way to do it using a List, which has a handy Insert method, as well as a Reverse method.
The Insert method lets you continue to add characters to the same index in the list (and the others after it are moved to higher indexes).
So, as you read the original string, you can keep inserting the characters at the start. Once you come to a delimeter, you add it to the end and adjust your insert position to be right after the delimeter.
When you're done, you just call Reverse and join the characters back to a string:
public static string ReverseWords(string words, char[] wordDelimeters)
{
var reversed = new List<char>();
int insertPosition = 0;
for(int i = 0; i < words.Length; i++)
{
var character = words[i];
if (wordDelimeters.Contains(character))
{
reversed.Add(character);
insertPosition = i + 1;
continue;
}
reversed.Insert(insertPosition, character);
}
reversed.Reverse();
return string.Join("", reversed);
}

Related

Moving the first char in a string to the send of the string using a method. C#

I know there are a lot of similar questions asked, and I've looked over those, but I still can't figure out my solution.
I'm trying to write a method that takes the first character of an inputted string and moves it to the back, then I can add additional characters if needed.
Basically if the input is Hello the output would be elloH + "whatever." I hope that makes sense.
As proof that I'm just not being lazy, here is the rest of the source code for the other parts of what I am working on. It all works, I just don't know where to begin with the last part.
Thanks for looking and thanks for the help!
private string CaseSwap(string str)//method for swaping cases
{
string result = ""; //create blank var
foreach (var c in str)
if (char.IsUpper(c)) //find uppers
result += char.ToLower(c); //change to lower
else
result += char.ToUpper(c); //all other lowers changed to upper
str = result; //assign var to str
return str; //return string to method
}
private string Reverse(string str)//method for reversing string
{
char[] revArray = str.ToCharArray(); //copy into an array
Array.Reverse(revArray); //reverse the array
return new string(revArray); //return the new string
}
private string Latin(string str)//method for latin
{
}
}
}
If you want to move first character to the end of string, then you can try below
public string MoveFirstCharToEnd(string str, string whateverStr="")
{
if(string.IsNullOrEmpty(str))
return str;
string result = str.Substring(1) + str[0] + whateverStr;
return result;
}
Note: I added whateverStr as an optional parameter, so that it can support only moving first character to the end and also it supports concatenating extra string to the result.
String.Substring(Int32):
Retrieves a substring from this instance. The substring starts at a
specified character position and continues to the end of the string.
Why not just take the 1st char and combine it with the rest of the string? E.g.
Hello
^^ ^
|| |
|Substring(1) - rest of the string (substring starting from 1)
|
value[0] - first character
Code:
public static string Rotate(string value) => string.IsNullOrEmpty(value)
? value
: $"{value.Substring(1)}{value[0]}";
Generalized implementation for arbitrary rotation (either positive or negative):
public static string Rotate(string value, int count = 1) {
if (string.IsNullOrWhiteSpace(value))
return value;
return string.Concat(Enumerable
.Range(0, value.Length)
.Select(i => value[(i + count % value.Length + value.Length) % value.Length]));
}
You can simplify your current implementation with a help of Linq
using System.Linq;
...
private static string CaseSwap(string value) =>
string.Concat(value.Select(c => char.IsUpper(c)
? char.ToLower(c)
: char.ToUpper(c)));
private static string Reverse(string value) =>
string.Concat(value.Reverse());
You can try to get the first character of a string with the String.Substring(int startPosition, int length) method . With this method you can also get the rest of your text starting from position 1 (skip the first character). When you have these 2 pieces, you can concat them.
Don't forget to check for empty strings, this can be done with the String.IsNullOrEmpty(string text) method.
public static string RemoveAndConcatFirstChar(string text){
if (string.IsNullOrEmpty(text)) return "";
return text.Substring(1) + text.Substring(0,1);
}
Appending multiple characters to a string is inefficient due to the number of string objects allocated, which is not just memory intensive it's also slow. There's a reason we have StringBuilder and other such options available to us, like working with char[]s.
Here's a fairly quick method that for rotating a string left one character (moving the first character to the end):
string RotateLeft(string source)
{
var chars = source.ToCharArray();
var initial = chars[0];
Array.Copy(chars, 1, chars, 0, chars.Length - 1);
chars[^1] = initial;
return new String(chars);
}
Sadly we can't do that in-place in the string itself since they're immutable, so there's no avoiding the temporary array and string construction at the end.
Based on the fact that you called the method Latin(...) and the bit of the question where you said: "Basically if the input is Hello the output would be elloH + "whatever."... I'm assuming that you're writing a Pig Latin translation. If that's the case, you're going to need a bit more.
Pig Latin is a slightly tricky problem because it's based on the sound of the word, not the letters. For example, onto becomes ontohay (or variants thereof) while one becomes unway because the word is pronounced the same as won (with a u to capture the vowel pronunciation correctly). Phonetic operations on English is quite annoying because of all the variations with silent and implied initial letters. And don't even get me started on pseudo-vowels like y.
Special cases aside, the most common rules of Pig Latin translation code appear to be as follows:
Words starting with a single consonant followed by a vowel: move the consonant to the end and append ay.
Words starting with a pair of consonants followed by a vowel: move the consonant pair to the end and append ay.
Words that start with a vowel: append hay, yay, tay, etc.
That third one is a bit difficult since choosing the right suffix is a matter of what makes the result easiest to say... which code can't really decide all that easily. Just pick one and go with that.
Of course there are plenty of words that don't fit those rules. Anything starting with a consonant triplet for example (Christmas being the first that came to mind, followed shortly by strip... and others). Pseudo-vowels like y mess things up (cry for instance). And of course the ever-present problem of correctly representing the initial vowel sounds when you've stripped context: won is converted to un-way vocally, so rendering it as on-way in text is a little bit wrong. Same with word, whose Pig Latin version is pronounced erd-way.
For a simple first pass though... just follow the rules, treating y as a consonant if it's the first letter and as a vowel in the second or third spots.
And since this is so often a homework problem, I'm going to stop here and let you play with it for a bit. Just in case :P
(Oh, and don't forget to preserve the case of your first character just in case you're working on a capitalized word. Latin should become Atinlay, not atinLay. Just saying.)

How do I get rid of double spaces without regex or any external methods?

This is an extra exercise given to us on our Uni course, in which we need to find whether a sentence contains a palindrome or not. Whereas finding if a word is a palindrome or not is fairly easy, there could be a situation where the given sentence looks like this: "Dog cat - kajak house". My logic is to, using functions I already wrote, first determine if a character is a letter or not, if not delete it. Then count number of spaces+1 to find out how many words there are in a sentence, prepare an array of those words and then cast a function that checks if a word is palindrome on every element of an array. However, the double space would mess everything up on a "counting" phase. I've spent around an hour fiddling with code to do this, however I can't wrap my head around this. Could anyone help me? Note that I'm not supposed to use any external methods or libraries. I've done this using RegEx and it was fairly easy, however I'd like to do this "legally". Thanks in advance!
Just split on space, the trick is to remove empties. Google StringSplitOptions.RemoveEmptyEntries
then obviously join with one clean space
You could copy all the characters you are interested in to a new string:
var copy = new StringBuilder();
// Indicates whether the previous character was whitespace
var whitespace = true;
foreach (var character in originalString)
{
if (char.IsLetter(character))
{
copy.Append(character);
whitespace = false;
}
else if (char.IsWhiteSpace(character) && !whitespace)
{
copy.Append(character);
whitespace = true;
}
else
{
// Ignore other characters
}
}
If you're looking for the most rudimentary/olde-worlde option, this will work. But no-one would actually do this, other than in an illustrative manner.
string test = "Dog cat kajak house"; // Your string minus any non-letters
int prevLen;
do
{
prevLen = test.Length;
test = test.Replace(" ", " "); // Repeat-replace double spaces until none left
} while (prevLen > test.Length);
Personally, I'd probably do the following to end up with an array of words to check:
string[] words = test.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

Using string.ToUpper on substring

Have an assignment to allow a user to input a word in C# and then display that word with the first and third characters changed to uppercase. Code follows:
namespace Capitalizer
{
class Program
{
static void Main(string[] args)
{
string text = Console.ReadLine();
char[] delimiterChars = { ' ' };
string[] words = text.Split(delimiterChars);
string Upper = text.ToUpper();
Console.WriteLine(Upper);
Console.ReadKey();
}
}
}
This of course generates the entire word in uppercase, which is not what I want. I can't seem to make text.ToUpper(0,2) work, and even then that'd capitalize the first three letters. Only solution I can think of now that would make the word appear on one line (and I don't know if it works) is to move the capitalized letters and lowercase letters into a character array and try to get that to print all values in a modified order.
The simplest way I can think of to address your exact question as described — to convert to upper case the first and third characters of the input — would be something like the following:
StringBuilder sb = new StringBuilder(text);
sb[0] = char.ToUpper(sb[0]);
sb[2] = char.ToUpper(sb[2]);
text = sb.ToString();
The StringBuilder class is essentially a mutable string object, so when doing these kinds of operations is the most fluid way to approach the problem, as it provides the most straightforward conversions to and from, as well as the full range of string operations. Changing individual characters is easy in many data structures, but insertions, deletions, appending, formatting, etc. all also come with StringBuilder, so it's a good habit to use that versus other approaches.
But frankly, it's hard to see how that's a useful operation. I can't help but wonder if you have stated the requirements incorrectly and there's something more to this question than is seen here.
You could use LINQ:
var upperCaseIndices = new[] { 0, 2 };
var message = "hello";
var newMessage = new string(message.Select((c, i) =>
upperCaseIndices.Contains(i) ? Char.ToUpper(c) : c).ToArray());
Here is how it works. message.Select (inline LINQ query) selects characters from message one by one and passes into selector function:
upperCaseIndices.Contains(i) ? Char.ToUpper(c) : c
written as C# ?: shorthand syntax for if. It reads as "If index is present in the array, then select upper case character. Otherwise select character as is."
(c, i) => condition
is a lambda expression. See also:
Understand Lambda Expressions in 3 minutes
The rest is very simple - represent result as array of characters (.ToArray()), and create a new string based off that (new string(...)).
Only solution I can think of now that would make the word appear on one line (and I don't know if it works) is to move the capitalized letters and lowercase letters into a character array and try to get that to print all values in a modified order.
That seems a lot more complicated than necessary. Once you have a character array, you can simply change the elements of that character array. In a separate function, it would look something like
string MakeFirstAndThirdCharacterUppercase(string word) {
var chars = word.ToCharArray();
chars[0] = chars[0].ToUpper();
chars[2] = chars[2].ToUpper();
return new string(chars);
}
My simple solution:
string text = Console.ReadLine();
char[] delimiterChars = { ' ' };
string[] words = text.Split(delimiterChars);
foreach (string s in words)
{
char[] chars = s.ToCharArray();
chars[0] = char.ToUpper(chars[0]);
if (chars.Length > 2)
{
chars[2] = char.ToUpper(chars[2]);
}
Console.Write(new string(chars));
Console.Write(' ');
}
Console.ReadKey();

Select a part of string when find a character

I need to select a part of a string ,suppose i have a string like this :Hello::Hi,
I use this characters :: as a separator, so i need to separate Hello and Hi.I am using C# application form .
I googled it ,i found something like substring but it didn't help me.
Best regards
string.Split is the right method, but the syntax is a little tricky when splitting based on a string versus a character.
The overload to split on a string takes the input as an array of strings so it can be distinquished from the overload that takes an array of characters (since a string can be easily cast to an array of characters), and adds a parameter for StringSplitEntries, which you can set to None to use the default option (include "empty" entries):
string source = "Hello::Hi";
string[] splits = source.Split(new string[] {"::"}, StringSplitOptions.None);
You can split a string into multiple parts based on a semaphore using the Split function:
var stringToSearch = "Hello::Hi";
var foundItems = stringToSearch.Split(new[] {"::"},
StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < foundItems.Count(); i++)
{
Console.WriteLine("Item #{0}: {1}", i + 1, foundItems[i]);
}
// Ouput:
// Item #1: Hello
// Item #2: Hi

Extracting words From a comma separated string without using an array

Are there any in built libraries in c# to Extract words From a comma separated string without using an array.
ya i know of split function but if i'm right we need to use an array for it...
i dont want to use an array...
You could do a very nasty for loop where you search for the , values and then compare from the start of 1 , to the next. You could use SubString() and IndexOf() to achieve this, but this isn't very performant nor elegant.
Considering your comment on your own post, I assume this is what you want:
String myString = "this,is,a,string";
String separator = ",";
MethodName(myString.Split(separator.ToCharArray()));
...
public void MethodName(String[] words) {
// do stuff here
}
If not, clarify your question.
EDIT
Please, PLEASE just be more clear with your question. What do you wish to check? If a word matches a certain pattern? If the word exists at all?
How about trying from a different angle.
You could loop through your words to compare and check if they exist in a given string e.g.
string listOfWords = "Some, text, to, look, through";
if (WordExists(listOfWords, "look"))
{
}
private bool WordExists(string listToCheck, string wordToFind)
{
return listToCheck.Contains(wordToFind);
}
You can use the String.Split() method
var myString = "Hello, World, I, am, a, comma, separated, string"
foreach (var item in myString.Split(new Char [] {',')) {
// ...
}

Categories

Resources