How to fix Join(" ") doesnt add a space to the concatenated string - c#

When i try to Join() an array with words and try to add a space to it,
The space seems to be left out, any idea why?
A little background info, when i try to reverse a string of words given to me so that
"hi my name is" should become "is name my hi"
public static string ReverseWords(string text)
{
string[] words = text.Split(' ');
string s = "";
for (int i = words.Length - 1; i >= 0; i--)
{
s+= string.Join(" ", words [i]);
}
return s;
}
The expected outcome would have been: "world! hello"
But it was: "world!hello"
As you can see I'm missing the space between world! and hello.
Any ideas?

You're calling Join with a single word at a time, using the overload accepting a parameter array. Joining a single item will always just return that item - there's nothing else to join it with.
Instead of that, just call it with all the words, in reverse order:
public static string ReverseWords(string text)
{
string[] words = text.Split(' ');
return string.Join(" ", words.Reverse());
}

Join combines the elements of the array with the specified separator, but you are adding each element separately. So no space is added.
string.Join(" ", words.Reverse());

string.Join() is designed to work on a list of strings, placing the separator char between each. You're only giving it one at a time, hence no separator. Try this:
public static string ReverseWords(string text)
{
string[] words = text.Split(' ');
return string.Join(" ", words.Reverse());
}

sorry that it took me a while guys, im still a beginner.
But the .Reverse() function wasnt it because it would turn every char in the word backwards, which wasnt my objective.
The trick was as following:
public static string ReverseWords(string text)
{
string[] words = text.Split(' ');
string s = words[words.Length - 1];
for (int i = words.Length - 2; i >= 0; i--)
{
s+= " " + words[i];
}
return s;
}
}
really alot of thanks with guiding.
#igor you where right, i kept trying to do this exercise in an online environment when i copied it to VS i could discover what was wrong by slowly debugging.

Related

Reverse the words in a string without using builtin functions like split and substring in C#

I wrote the following:
class Program
{
public static void Main(string[] args)
{
string name = "Hello World"
StringBuilder builder = new StringBuilder();
for (int i = name.Length - 1; i >= 0; i--)
{
builder.Append(name[i]);
}
string newName =builder.ToString();
Console.WriteLine(newName);
}
}
I am getting "dlrow olleh " as output. I want "World Hello ".
I wrote a quick solution which uses 2 loops.
The first loop is iterating over the string from left to right.
When it encounters a whitespace (which delimits a word) the second loop starts.
The second loop is looping through the word from right to left. The second loop can not go from left to right because we have no idea where the word will begin (unless we would remember where we met the previous whitespace). Hence the second loop iterates from right to left through the string until it encounters a whitespace (beginning of the word), or until the index becomes 0 (which is a corner case). The same corner case can be observed in the first loop.
Here it is :
String name = "Hello World";
StringBuilder builder = new StringBuilder();
for (int i = 0; i < name.length(); i++)
{
char tmp = name.charAt(i);
if(tmp == ' ' || i == name.length() - 1) {
// Found a whitespace, what is preceding must be a word
builder.insert(0, ' ');
for(int j = i - 1; j >= 0; j--) {
if(i == name.length() - 1 && j == i - 1) {
// Exceptional case (necessary because after the last word there is no whitespace)
builder.insert(0, name.charAt(i));
}
char curr = name.charAt(j);
if(curr == ' ') {
// We passed the beginning of the word
break;
}
else if(j == 0) {
builder.insert(0, curr);
break;
}
//builder.append(curr);
builder.insert(0, curr);
}
}
}
String newName = builder.toString();
System.out.println(newName);
Note that this is java code but it should be straightforward to translate it to C#.
In pseudo code, a solution to this problem might look something like this:
result = empty string
last = input.length
for i from input.length - 1 to 0
if input(i) is whitespace or i is 0
for j from i to last - 1
append input[j] to result
last = i
This starts at the back of the string, and loops backwards. When it finds a whitespace (or gets to the beginning of the stirng), it knows it has found a complete word and adds it to the list. The variable last keeps track of where the last word that got added started.
You will have to tweak this a bit to get the spaces between the words right.
Just because you can't use "built-in" functions, doesn't mean you can't write your own. What you should be learning from a task like this is how to break a problem down into a set of sub problems.
string Reverse(string pInput) {
// iterate backwards over the input, assemble a new string, and return it
}
List<string> Split(string pInput, char pSplitOn) {
// iterate forwards over the input
// build up a new string until the split char is found
// when it is found, add the current string to a list
// and start the building string over at empty
// maybe only add strings to the list if they aren't empty
// (although that wouldn't preserve extra whitespace, which you may want)
// make sure to add the end of the string since it probably
// doesn't end with the split char
// return the list
}
string Join(List<string> pWords, char pSeparator) {
// build up a new string consisting of each of the words separated by the separator
}
string ReverseWords(string pInput) {
// split the input on a space
// for each "word" in the resulting list, reverse it
// join the reversed words back together into one string, with spaces separating them
}
This assumes that the only whitespace that you will encounter consists of spaces. Also assumes you're allowed to use List<T>.

Remove spaces from a string C# (something simple!)

Hi guys I can't find out why my code is not working, any help would be really appreciated!
I have a given string filled with numbers and space between each number I have to remove the spaces so that I get all the numbers glued to each other..
string nums = "1 2 3 4 5";
for (int i = 0; i < nums.Length; i++)
{
if (nums[i].ToString() == " ")
{
nums[i].ToString() = "";
}
}
I also tried using .Replace(" ", ""); but again no success, I can't figure out where I'm doing it wrong.. I need a simple, beginner friendly solution!
Strings in .NET are immutable. Calling nums[i].ToString() gives you a new string, without modifying nums.
Replace is the way to go, but you have to assign result back to nums:
string nums = "1 2 3 4 5";
nums = nums.Replace(" ", "");
It's necessary, because Replace does not modify source string. It returns new one instead.
This method will remove the spaces out of your string. What it does is iterates through each char and then compares it to the UTF-16 value for space. If it's a space it won't add it.
public String RemoveSpaces(String withSpaces){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < withSpaces.Length; i++)
{
if (withSpaces[i] != 32)
{
sb.Append(withSpaces[i]);
}
}
return sb.ToString();
}
You're assigning to the output of a function call (ToString()) which is wrong. Use String.Replace to replace characters in a string.

How to make a string from arrays with only Uppercase items?

I have a list of names (cyclists) in order of Lastname, Firstname. I want to run code So it puts Lastname in front of Firstname. The Lastname is always written in uppercase and can contain one more values. So i decided to string split to array, that works. Only putting it together is hard.
here is my code so far: (tried it with for and foreach)
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string fullName = "BELAMONTE VALVERDE Allechandro Jesus";
string[] words = fullName.Split(' ');
foreach (string word in words)
if (word.ToUpper() == word)
{
string lastname = string.Join(" ", word);
Console.WriteLine(word);
}
Console.ReadLine();
string fullName2 = "GONZALEZ GALDEANO Igor Anton";
string[] words2 = fullName2.Split(' ');
for (int i = 0; i < words2.Length; i++)
{
string word2 = words2[i];
if (word2.ToUpper() == word2)
{
string lastname2 = string.Join(" ", word2);
Console.WriteLine(lastname2);
}
}
Console.ReadLine();
}
}
}
It gives a output like
BELAMONTE VALVERDE
BELAMONTE VALVERDE
I want that to be on one line. The actual use wil be read a record from a table convert that
and Replace that for the loaded item.
The first thing you want to do is encapsulate the logic that's testing whether part of a string is uppercase:-
Detecting if a string is all CAPS
public bool IsAllUppercase(string value)
{
return value.All(x => x.IsUpper);
}
Then you want to encapsulate the logic that's extracting the uppercase part of your name
public string GetUppercasePart(string value)
{
return string.Join(" ", value.Split(" ").Where(x => IsAllUppercase(x));
}
Then getting the uppercase part of the name is really simple:-
var lastName = GetUppercasePart("BELAMONTE VALVERDE Allechandro Jesus");
I get the impression, though, that there's more to your problem than just getting all of the uppercase words in a string.
WARNING: If this is code for a production application that you're going to run anywhere other than your computer, then you want to take into account that IsUpper means different things in different locales. You might want to read up on how internationalisation concerns affect string manipulation:-
http://support.microsoft.com/kb/312890
In C# what is the difference between ToUpper() and ToUpperInvariant()?
C# String comparisons: Difference between CurrentCultureIgnoreCase and InvariantCultureIgnoreCase
If you know that lastname will be all UPPERCASED and will be in front of first name, you can use regex for parsing uppercased letters and the rest of the name.
This is the regex:
([A-Z\s]+) (.*)
This one will match uppercased words where a space can be between them, that's the \s
([A-Z\s]+)
This one will match the rest of the name
(.*)
So the final code for switching one name could look like this:
static void Main(string[] args)
{
string fullName = "BELAMONTE VALVERDE Allechandro Jesus";
string pattern = #"([A-Z\s]+) (.*)";
var parsedName = Regex.Match(fullName,pattern);
string firstName = parsedName.Groups[2].ToString();
string lastName = parsedName.Groups[1].ToString();
string result = firstName + " " + lastName;
}
You have a code design problem here:
foreach (string word in words)
if (word.ToUpper() == word)
{
string lastname = string.Join(" ", word);
Console.WriteLine(word);
}
What you want to do is to write the lastname once, right? So let's split the algorithm:
Get all words from the string: done string[] words = fullName.Split(' ');
Read first word, if it's uppercase, save it
Repeat 2 for the next word until it isn't uppercase
Join all the saved words
Print the result
We don't need to "save" the words thanks to a handy class named StringBuilder, so it would go like this:
string fullName = "BELAMONTE VALVERDE Allechandro Jesus";
string[] words = fullName.Split(' ');
StringBuilder sb = new StringBuilder();
foreach (string word in words)
if (word.ToUpper() == word)
{
sb.Append(word + " ");
}
else
break; // That's assuming you will never have a last name's part after a first name's part :p
if (sb.Length > 0)
sb.Length--; // removes the last " " added in the loop, but maybe you want it ;)
Console.WriteLine(sb.ToString());
string[] newArr = (from x in asda
select x.ToUpper()).ToArray();

Go to each white space in a string. C#

Is it possible to pass over a string, finding the white spaces?
For example a data set of:
string myString = "aa bbb cccc dd";
How could I loop through and detect each white space, and manipulate that space?
I need to do this in the most effecient way possible.
Thanks.
UPDATE:
I need to manipulate the space by increasing the white space from an integer value. So for instance increase the space to have 3 white spaces instead of one. I'd like to make it go through each white space in one loop, any method of doing this already in .NET? By white space I mean a ' '.
You can use the Regex.Replace method. This will replace any group of white space character with a dash:
myString = Regex.Replace(myString, "(\s+)", m => "-");
Update:
This will find groups of space characters and replace with the tripple amount of spaces:
myString = Regex.Replace(
myString,
"( +)",
m => new String(' ', m.Groups[1].Value.Length * 3)
);
However, that's a bit too simple to make use of regular expressions. You can do the same with a regular replace:
myString = myString.Replace(" ", " ");
This will replace each space intead of replace groups of spaces, but the regular replace is much simpler than Regex.Replace, so it should still be at least as fast, and the code is simpler.
If you want to replace all whitespace in one swoop, you can do:
// changes all strings to dashes
myString.Replace(' ', '-');
If you want to go case by case (that is, not just a mass replace), you can loop through IndexOf():
int pos = myString.IndexOf(' ');
while (pos >= 0)
{
// do whatever you want with myString # pos
// find next
pos = myString.IndexOf(' ', pos + 1);
}
UPDATE
As per your update, you could replace single spaces with the number of spaces specified by a variable (such as numSpaces) as follows:
myString.Replace(" ", new String(' ', numSpaces));
If you just want to replace all spaces with some other character:
myString = myString.Replace(' ', 'x');
If you need the possibility of doing something different to each:
foreach(char c in myString)
{
if (c == ' ')
{
// do something
}
}
Edit:
Per your comment clarifying your question:
To change each space to three spaces, you can do this:
myString = myString.Replace(" ", " ");
However note that this doesn't take into account instances where your input string already has two or more spaces. If that is a possibility you will want to use a regex.
Depending on what you're tring to do:
for(int k = 0; k < myString.Length; k++)
{
if(myString[k].IsWhiteSpace())
{
// do something with it
}
}
The above is a single pass through the string, so it's O(n). You can't really get more efficient that that.
However, if you want to manipulate the original string your best bet is to Use a StringBuilder to process the changes:
StringBuilder sb = new StringBuilder(myString);
for(int k = 0; k < myString.Length; k++)
{
if(myString[k].IsWhiteSpace())
{
// do something with sb
}
}
Finally, don't forget about Regular Expressions. It may not always be the most efficient method in terms of code run-time complexity but as far as efficiency of coding it may be a good trade-off.
For instance, here's a way to match all white spaces:
var rex = new System.Text.RegularExpressions.Regex("[^\\s](\\s+)[^\\s]");
var m = rex.Match(myString);
while(m.Success)
{
// process the match here..
m.NextMatch();
}
And here's a way to replace all white spaces with an arbitrary string:
var rex = new System.Text.RegularExpressions.Regex("\\s+");
String replacement = "[white_space]";
// replaces all occurrences of white space with the string [white_space]
String result = rex.Replace(myString, replacement);
Use string.Replace().
string newString = myString.Replace(" ", " ");
LINQ query below returns a set of anonymous type items with two properties - "sybmol" represents a white space character, and "index" - index in the input sequence. After that you have all whitespace characters and a position in the input sequence, now you can do what you want with this.
string myString = "aa bbb cccc dd";
var res = myString.Select((c, i) => new { symbol = c, index = i })
.Where(c => Char.IsWhiteSpace(c.symbol));
EDIT: For educational purposes below is implementation you are looking for, but obviously in real system use built in string constructor and String.Replace() as shown in other answers
string myString = "aa bbb cccc dd";
var result = this.GetCharacters(myString, 5);
string output = new string(result.ToArray());
public IEnumerable<char> GetCharacters(string input, int coeff)
{
foreach (char c in input)
{
if (Char.IsWhiteSpace(c))
{
int counter = coeff;
while (counter-- > 0)
{
yield return c;
}
}
else
{
yield return c;
}
}
}
var result = new StringBuilder();
foreach(Char c in myString)
{
if (Char.IsWhiteSpace(c))
{
// you can do what you wish here. strings are immutable, so you can only make a copy with the results you want... hence the "result" var.
result.Append('_'); // for example, replace space with _
}
else result.Append(c);
}
myString = result.ToString();
If you want to replace the white space with, e.g. '_', you can using String.Replace.
Example:
string myString = "aa bbb cccc dd";
string newString = myString.Replace(" ", "_"); // gives aa_bbb_cccc_dd
In case you want to left/right justify your string
int N=10;
string newstring = String.Join(
"",
myString.Split(' ').Select(s=>s.PadRight(N-s.Length)));

How to remove words based on a word count

Here is what I'm trying to accomplish. I have an object coming back from
the database with a string description. This description can be up to 1000
characters long, but we only want to display a short view of this. So I coded
up the following, but I'm having trouble in actually removing the number of
words after the regular expression finds the total count of words. Does anyone
have good way of dispalying the words which are less than the Regex.Matches?
Thanks!
if (!string.IsNullOrEmpty(myObject.Description))
{
string original = myObject.Description;
MatchCollection wordColl = Regex.Matches(original, #"[\S]+");
if (wordColl.Count < 70) // 70 words?
{
uxDescriptionDisplay.Text =
string.Format("<p>{0}</p>", myObject.Description);
}
else
{
string shortendText = original.Remove(200); // 200 characters?
uxDescriptionDisplay.Text =
string.Format("<p>{0}</p>", shortendText);
}
}
EDIT:
So this is what I got working on my own:
else
{
int count = 0;
StringBuilder builder = new StringBuilder();
string[] workingText = original.Split(' ');
foreach (string word in workingText)
{
if (count < 70)
{
builder.AppendFormat("{0} ", word);
}
count++;
}
string shortendText = builder.ToString();
}
It's not pretty, but it worked. I would call it a pretty naive way of doing this. Thanks for all of the suggestions!
I would opt to go by a strict character count rather than a word count because you might happen to have a lot of long words.
I might do something like (pseudocode)
if text.Length > someLimit
find first whitespace after someLimit (or perhaps last whitespace immediately before)
display substring of text
else
display text
Possible code implementation:
string TruncateText(string input, int characterLimit)
{
if (input.Length > characterLimit)
{
// find last whitespace immediately before limit
int whitespacePosition = input.Substring(0, characterLimit).LastIndexOf(" ");
// or find first whitespace after limit (what is spec?)
// int whitespacePosition = input.IndexOf(" ", characterLimit);
if (whitespacePosition > -1)
return input.Substring(0, whitespacePosition);
}
return input;
}
One method, if you're using at least C#3.0, would be a LINQ like the following. This is provided you're going strictly by word count, not character count.
if (wordColl.Count > 70)
{
foreach (var subWord in wordColl.Cast<Match>().Select(r => r.Value).Take(70))
{
//Build string here out of subWord
}
}
I did a test using a simple Console.WriteLine with your Regex and your question body (which is over 70 words, it turns out).
You can use Regex Capture Groups to hold the match and access it later.
For your application, I'd recommend instead simply splitting the string by spaces and returning the first n elements of the array:
if (!string.IsNullOrEmpty(myObject.Description))
{
string original = myObject.Description;
string[] words = original.Split(' ');
if (words.Length < 70)
{
uxDescriptionDisplay.Text =
string.Format("<p>{0}</p>", original);
}
else
{
string shortDesc = string.Empty;
for(int i = 0; i < 70; i++) shortDesc += words[i] + " ";
uxDescriptionDisplay.Text =
string.Format("<p>{0}</p>", shortDesc.Trim());
}
}
Are you wanting to remove 200 characters or start truncating at the 200th character? When you call original.Remove(200) you are indexing the start of the truncation at the 200th character. This is how you use Remove() for a certain number of characters to remove:
string shortendText = original.Remove(0,200);
This starts at the first character and removes 200 starting with that one. Which I imagine that's not what you're trying to do since you're shortening a description. That's merely the correct way to use Remove().
Instead of using Regex matchcollections why not just split the string? It's a lot easier and straight forward. You can set the delimiter to a space character and split that way. Not sure if that completely fixes your need but it just might. I'm not sure what your data looks like in the description. But you split this way:
String[] wordArray = original.Split(' ');
From there you can determine the word count with wordArray's Length property value.
If I was you I would go by characters as you may have many one letter words or many long words in your text.
Go through until characters <= your limit, then either find the next space and then add these characters to a new string (possibly using the SubString method) or take these characters and add a few full stops, then make a new string The later could be unproffessional I suppose.

Categories

Resources