tags:

views:

174

answers:

8

My strings are of this kind: City (PR) from a Database, where PR stands for Province.

At the end I want two separate variables. City and PR.

I have to do this with C#. Any idea? Thanks.

+9  A: 

Regex?

You can divide your pattern into capture groups and go from there.

(.*)(\(.*\))

That will capture the city in the first group and your PR/Province part in the second.

Edit: madgnomes regex removes the paratheneses from the match, even if the Regex is getting scary at this point :)

Kirschstein
I'm a noob with Regular Expressions, can u explain it better? Thank you.
Alex
Shouldn't you escape the outside parens so the capture group has just "PR" in it, not "(PR)"?
Michael Haren
To be a fair comparison to @dtb's excellent solution, this should be coded up. Its brevity is compelling now but I'm curious if that'll hold up
Michael Haren
This solution is too simple but good as an example. See http://stackoverflow.com/questions/2874442/help-with-manipulating-some-strings/2874525#2874525 for a better solution.
artur02
+13  A: 

Assuming cities don't contain ( characters:

string s = "City (PR)";
int p = s.LastIndexOf("(");

string city = s.Substring(0, p).Trim();
string province = s.Substring(p + 1, s.Length - p - 2).Trim();

city is the substring from the first character up to but not including the last ( character.
province is the substring from the first character after the last ( to the end excluding the last character.

dtb
+1 nice and clean, and handles city names better; might consider using [`LastIndexOf`](http://msdn.microsoft.com/en-us/library/0w96zd3d.aspx) to make it even more robust
Michael Haren
Thanks, haven't considered IndexOf. This should work.
Alex
You should use Regex, like madgnome suggested
Gabriel Mongeon
+1  A: 

If the province is always in parenthesis, and the city name won't have any parenthesis, you can use the Split function.

string foo = "City (PR)";
string[] bar = foo.Split('(');

The bar variable will have the city in the first column of the array, and the province in the second (although you'll want to remove the right parenthesis).

LittleBobbyTables
I want to give you upvotes based on your nickname.
Kirschstein
Hah, thanks, apparently I need it.
LittleBobbyTables
this should work, even if i have to remove tha last parenthesis from PR with a substring.
Alex
Could probably get around this with `string[] bar = foo.Split("()".ToCharArray(),3)`, which would give you bar[0] is the city, and bar[1] at the province...
ZombieSheep
+2  A: 

You have a couple of methods on string one of them being Split.

Example

var s = "City (PR)";
var words = s.Split(' ');
foreach (string word in words)
{
    Console.WriteLine(word);
}

That would print:

City

(PR)

You can also do it like this

var words = s.Split(' ');
var city = words[0];
var pr = words[1];

You can just remove the paranthesis with other string methods if you like.

One might argue that this is not the best way to do it. It's simple and give's you want you want. As others suggested, regex is probably the "cleanest" way to do it.

Note

If you want to support cities with spaces in the name, this method won't work out that well for you. I would then suggest one of the other answers posted.

Filip Ekberg
What if the city is two words? Like New York?
Kirschstein
New York, San Francisco, La Paz...
Gregoire
That's over engineering it! Why would one think outside the box?.. Joke. Didn't think of cities with 2 words, since we don't have them were i live..
Filip Ekberg
@Filip EkbergWhat about Lilla Edet? ;-)
daft
@daft, Ok so 1 city here has a space in it, chaning my code would be like.. supporting IE6 ;) Anyways, my example works with basic string manipulation and now tells the OP that it won't work with spaces in the words.
Filip Ekberg
@FilipOnly kidding. i struggled hard to come up with Lilla Edet to be honest. :-)
daft
+1  A: 

Any chance you can modify the DB design to have a different field to hold whether it's a province or a state? This is a horrible design, and in order to get around it you definitely need to write some ugly code... Something along the lines of

if(CityAndProvinceOrStateIndicator.Contains(" (PR)"))
{
   // This is a province.
   // Get the city name only
   string CityNameOnly = CityAndProvinceOrStateIndicator.Replace(" (PR)", "");


}
elseif...
David Stratton
+1  A: 

Although excellent parsing options have been mentioned, I'd just like to suggest that you consider going to the source and modifying your database query and possibly even the database itself.

Obviously that's not always possible, which is probably why you're asking the question in the way you are, but the fact that you're receiving data in this way implies to me that the data needs to be structured or obtained differently.

Randolpho
Is what I'm trying to do infact ;)
Alex
I second that opinion. +1.
David Stratton
@Alex: Good. Always push for fixing the system "the right way", even if you don't get the chance to actually do it this time around. Without that push, your company will stagnate technologically, and that's bad. Unfortunately, it's rare for anyone outside of the technology to understand that, hence the need for the pushback.
Randolpho
+12  A: 

You can use Regex and named groups.

string resultString = "New York (New York)";
Regex regexObj = new Regex(@"(?<City>[^(]*)\((?<PR>[^)]*)\)",RegexOptions.IgnoreCase);

var match = regexObj.Match(subjectString);
if (match.Success)
{
  string city = match.Groups["City"].Value.Trim();
  string province = match.Groups["PR"].Value;
}

Regex explanation

(?<City>[^(]*)\((?<PR>[^)]*)\) :

  • (?<City>XXX) defines a group named City
    • [^(]* matches any character that is not a ( between 0 and unlimited times
  • \( matches a ( one time
  • (?<PR>XXX) defines a group named PR
    • [^)]* matches any character that is not a ) between 0 and unlimited times
  • \) matches a ) one time
madgnome
wow, this seems very strong. Should I try it now.
Alex
Regex is the way to go! This was made for that kind of tasks.
Gabriel Mongeon
A: 

Let the following SQL SELECT statement do all the work for you:

SELECT [Name], [Address], 
       LTRIM(RTRIM(LEFT([CityProv],CHARINDEX('(',[CityProv])-1))) as City, 
       LTRIM(RTRIM(SUBSTRING( [CityProv],
             CHARINDEX('(',[CityProv]) + 1,
             CHARINDEX(')',[CityProv]) - CHARINDEX('(',[CityProv]) - 1))) as Prov, 
       [PostalCode]
FROM Stackoverflow

Here is the dataset I created for testing:

Joel,1 Software St,NewYork (NY),12345
Jeff,321 Horror Lane,San somewhere ( CAL),90210
Zamboni,888 Wpf Rd,Vancouver (Britsh Columbia ),V0S1A0
Bill,7 Main St,Vista( WA ),77777

Zamboni