tags:

views:

462

answers:

3

I've got city, state, country strings like:

NEW YORK, NY, US
REDMOND, WA, US
US
HONG KONG
CALGARY, CA
E. SYRACUSE, NY, US

I'd like to transform them to their proper case (New York, NY, US; etc). Whats a quick way to do this in PHP?

+1  A: 

What do you mean by 'proper case'? I have a feeling I'm missing something as far as what you exactly need so it'd be nice if you could clarify exactly what this data is and how you want to handle it.

You can use ucfirst to make the first letter of each word uppercase, and you can use explode to separate the string into the respective segments:

$str = "NEW YORK, NY, US";
list($city, $state, $country) = explode(',', $str);
$city = ucfirst(strtolower($city));

In the examples you gave you wouldn't need to do anything to state and country, although there is strtoupper if you want to guarantee they are uppercase.

This is a tricky proposition, however, as I am sure there are situations in which whatever output this gives may not be the "correct" way to write a particular city, although I can't think of any examples off the top of my head I am sure there are some.

I'm also noticing there are a few lines that just have a country ("US") and some that just have a city ("HONG KONG") - there's no reliable way to determine what the string contains. You could try matching it with a list of countries and cities and so forth, but it seems like whatever solution you come up with it's going to be a guessing game at best.

Paolo Bergantino
+1 for the fact that you used strtolower before ucfirst!
St. John Johnson
+1  A: 
$locs = array(
  'NEW YORK, NY, US',
  'REDMOND, WA, US',
  'US',
  'HONG KONG',
  'CALGARY, CA',
  'E. SYRACUSE, NY, US',
);
foreach ($locs as &$loc) {
  $items = explode(',', $loc);
  if (strlen($items[0]) > 2) {
    $items[0] = ucwords($items[0]);
  }
  $loc = implode(',', $items);
}
cletus
Is all he wants proper casing? I don't know why I got the impression from the question he wanted to be able to determine whether 'US' and 'HONG KONG' are a country or a state or whatever. Re-reading the question I think I just read too much into it. In either case, you want to wrap the $items[0] with strtolower before calling ucwords
Paolo Bergantino
@Paolo: that's how I read it
cletus
A: 

Without a dictionary there will always be some edge cases, so I think this approach would be the best

vinko@parrot:~$ cat cap.php
<?php

$list = "NEW YORK, NY, US
REDMOND, WA, US
US
HONG KONG
CALGARY, CA
E. SYRACUSE, NY, US";

$countries = array("HONG KONG", "US", "CA");
$states = array("NY","WA");

$list = split("\n",$list);

$out = "";
foreach ($list as $line) {
        list($first,$second,$third) = split(",",$line);

        //Here you check in a dictionary for country/state to
        //like this:

        if (!in_array($first,$countries) && !in_array($first,$states)) {
                $first = ucwords(strtolower($first));
        }
        if ($third) { $out.= $first.",".$second.",".$third; }
        else if ($second && !$third) { $out.= $first.",".$second; }
        else { $out.= $first; }
        $out.= "\n";
}
echo $out;
?>
vinko@parrot:~$ php cap.php
New York, NY, US
Redmond, WA, US
US
HONG KONG
Calgary, CA
E. Syracuse, NY, US
Vinko Vrsalovic