2

I have a bunch of lat/long pairs as a string:

-94.5555,95.5555

The API I'm using requires they be switched:

95.555,-94.555

Is there any slick, short way of doing this?

chum of chance
  • 6,200
  • 10
  • 46
  • 74

8 Answers8

13

One-liner with Linq:

string.Join(",", original.Split(',').Reverse());

Or, more explicit (might be a performance improvement):

string[] split = original.Split(',');
string reversed = split[1] + "," + split[0];
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • You'll want a `ToArray()` call after `Reverse` since LINQ's `Reverse` returns an `IEnumerable`, not an array, which `Join` wants. – Sarah Vessels Sep 16 '10 at 18:26
  • 2
    @Sarah: .NET 4 has new overloads for string.Join. – Jon Skeet Sep 16 '10 at 18:27
  • 2
    I know that we're talking about a lat/long pair, but watch out for the thousand separator should you except such data to be given to your function. – Pierre-Alain Vigeant Sep 16 '10 at 18:30
  • I have to use it in a non-static context so Join doesn't work. I gave Jon Skeet the best answer, but this was very pretty so I gave you a point. – chum of chance Sep 16 '10 at 18:42
  • What is it about your context that makes this approach not work? – recursive Sep 16 '10 at 18:44
  • 2
    @chum: Why would being in a non-static context stop `Join` from working? You can absolutely use this answer in any context you like. Personally I'd still rather have a well-named method call which hides the details, but this would definitely work. – Jon Skeet Sep 16 '10 at 18:45
  • The compiler is throwing up a warning: Cannot access static method 'Join' in non-static context. I didn't really investigate why though, it might be because my properties are virtual? public virtual string ReverseObject { get { return LatLong.Join... } } I agree with you on the well named-method calls though. – chum of chance Sep 16 '10 at 19:01
  • 1
    @chum: You've changed the code. It should be `string.Join`, not `LatLong.Join`. Replace `original` with `LatLong`, not `string`. – Jon Skeet Sep 16 '10 at 19:48
3

Just write a method to do it, e.g. using string.IndexOf:

// Probably rename to reflect your specific usage
private static string SwitchSplitOnComma(string text)
{
    // Optional: validate that text is non-null
    int comma = text.IndexOf(',');
    // Optional: validate that there's a comma :)
    return text.Substring(comma + 1) + "," + text.Substring(0, comma);
}

Unless you need this for various purposes, I'd leave it as a specialist method in the class that needs it. Only promote it to a "general purpose utility method" (possibly parameterizing the delimiter etc) if you find you need the same functionality elsewhere.

Although you can do this in a single statement, I think the code is likely to be far easier to understand if you put it in a separate method - at which point it's fine to use a few easy-to-understand statements instead of one complicated and inefficient one :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Just as an aside, is there a reason you don't use String.Format? I always do, is there a reason I shouldn't that I don't know about? Not critiqueing, I just wonder why sometimes I see people doing it vs not doing it for concatenation.. – Jimmy Hoffa Sep 16 '10 at 18:28
  • @Jimmy I beilive in a situation like this the compiler will optimize it. – asawyer Sep 16 '10 at 18:30
  • I'm guessing String.Format() is slower because it has to parse the string then replace values? – Nelson Rothermel Sep 16 '10 at 18:31
  • Aye, just found another post about this, guess I should be using String.Concat, as + just reads grody to me. – Jimmy Hoffa Sep 16 '10 at 18:37
  • 1
    @Jimmy: "+" *does* use `String.Concat` under the covers, and IMO is more readable. As for using string.Format - again, I think that would be less readable than just stringing the values together, in this case. – Jon Skeet Sep 16 '10 at 18:43
  • I remember reading a post long ago which benchmarked StringBuilder vs. concatenation, and if you have less than ~4 strings, concatenation is faster. (String.Concat and String.Format both uses a StringBuilder internally) – Mikael Svenson Sep 16 '10 at 18:45
  • 1
    @Mikael: `String.Concat(string[])` uses unsafe code to allocate a single buffer for all of the strings and copy them into the buffer, not using a `StringBuilder` at all. `String.Concat` will always beat using a `StringBuilder` if the code is like `string s = a + b + c + d;` but not if there is a loop involved where strings are not concatenated inline. http://stackoverflow.com/questions/2708550/using-stringstringstring-vs-using-string-replace/2708565#2708565 – Callum Rogers Sep 16 '10 at 19:35
  • @Callum: You are right. I read the IEnumberable variants for .Net4. for Concat. – Mikael Svenson Sep 17 '10 at 09:46
3
String reversedLatLong = String.Join(",", yourString.Split(',').Reverse());
Jimmy Hoffa
  • 5,909
  • 30
  • 53
2

Building on Jon Skeet's, something more generic would be useful:

private static string Switch(this string text, char splitter)
{
    if(text != null && text.Length > 2) //Needs at least 3 letters for a valid switch
    {
        int position = text.IndexOf(splitter);
        if(position != -1) return text.Substring(position + 1) + splitter + text.Substring(0, position);
    }
    return text;
}

"99,-3432".Switch(',');
Blam
  • 2,888
  • 3
  • 25
  • 39
1
string myStr = "-94.5555,95.5555";
string[] components = myStr.Split(",")
components.Reverse();
string flippedStr = string.Join(",", components);
Sarah Vessels
  • 30,930
  • 33
  • 155
  • 222
1

Just for the heck of it. Here's a faster version, but you probably wouldn't need it :)

For 1.000.000 iterations compared to Jon Skeets clean version measured in seconds on my machine:

00:00:00.2145657 substring

00:00:00.0781270 unsafe

private unsafe static string SwitchSplitOnComma2(string text)
{
    int comma = text.IndexOf(',');
    string newString = string.Copy(text);
    fixed (char* src = text)
    {
        fixed (char* dst = newString)
        {
            int destCtr = 0;
            for (int i = comma + 1; i < text.Length; i++)
            {
                dst[destCtr++] = src[i];
            }
            dst[destCtr++] = ',';
            for (int i = 0; i < comma; i++)
            {
                dst[destCtr++] = src[i];
            }
        }
    }
    return newString;
}
Community
  • 1
  • 1
Mikael Svenson
  • 39,181
  • 7
  • 73
  • 79
0

The most efficient would be to modify/extend the API, since it parses the string anyway. Probably not an option, but I throw it out there...

Kendrick
  • 3,747
  • 1
  • 23
  • 41
0

How about this?

string oldString = "-94.5555,95.5555";
string newString = oldString .Substring(oldString .IndexOf(",") + 1) + "," + oldString .Substring(0, oldString .IndexOf(","));
Shoban
  • 22,920
  • 8
  • 63
  • 107