2012-04-09 3 views
8

У меня есть координаты долготы \ широты, сгруппированные вместе в строку, которую я хотел бы разделить на пары долготы \ широты. Благодаря stackoverflow я смог придумать некоторый linq, который разделит его на многомерный массив строк. Есть ли способ разделить строку непосредственно на объект, который принимает широту долготы и строковый массив, а затем создать объект?Есть ли лучший способ разделить эту строку с помощью LINQ?

string segment = "51.54398, -0.27585;51.55175, -0.29631;51.56233, -0.30369;51.57035, -0.30856;51.58157, -0.31672;51.59233, -0.3354" 

string[][] array = segment.Split(';').Select(s => s.Split(',')).ToArray(); 
foreach (string[] pair in array) 
{ 
//create object here 
} 
+1

Существует (почти?) Никогда не хороший способ разбить строку с помощью LINQ. Тем не менее, System.Text.RegularExpressions - это то, что вы хотите – sehe

+1

Что это такое '-0.3354", "London: 484" 'в конце вашей строки? –

+2

@sehe: Использование регулярного выражения для такой тривиальной задачи является излишним. вы знаете, что формат вашего ввода является постоянным, и что его легко разобрать, разделив вас * должен * использовать split вместо регулярного выражения. –

ответ

20

Вы близко. Нечто подобное могло бы помочь:

var pairSequence = segment.Split(';') 
     .Select(s => s.Split(',')) 
     .Select(a => new { Lat = double.Parse(a[0]), Long = double.Parse(a[1]) }); 
+0

@Alex Конечно, зависит от типа, который вам действительно нужен. Вы поняли эту идею. –

+0

Черт. Был в процессе написания почти что-то идентичного. Престижность. –

+0

Отлично, спасибо! Просто забыли новую часть {}. – NullReference

6

Предполагая, что у вас есть Coordinate класс с public Coordinate(double x, double y) конструктора, вы можете сделать это:

Coordinate[] result = segment 
    .Split(';') 
    .Select(s => s.Split(',')) 
    .Select(a => new Coordinate(x: double.Parse(a[0], NumberStyles.Number), 
           y: double.Parse(a[1], NumberStyles.Number)) 
    .ToArray(); 

или в равной степени

var query = from item in segment.Split(';') 
      let parts = item.Split(',') 
      let x = double.Parse(parts[0], NumberStyles.Number) 
      let y = double.Parse(parts[1], NumberStyles.Number) 
      select new Coordinate(x, y); 

Coordinate[] result = query.ToArray(); 
2

ли это необходимость, вы используете LINQ? Вы можете сделать все это со стандартной функцией разделения строк:

string[] pairsOfCoords = segment.Split(';'); 
List<CoordsObject> listOfCoords = new List<CoordsObject>(); 
foreach (string str in pairsOfCoords) 
{ 
    string[] coords = str.Split(','); 
    CoordsObject obj = new CoordsObject(coords[0], coords[1]); 
    listOfCoords.Add(obj); 
} 
+1

Да, но посмотрите, насколько он чище с linq. :) –

+1

@RobertP: Ну, я полагаю, это субъективно. Это выглядит довольно просто и чисто для меня. –

1

Я могу добавить немного больше. Благодаря dtb для начала, upvoted. Если вы нарушите функцию разбора, вы можете более чисто обрабатывать условия ошибки, например, неправильное количество элементов в вашем массиве или вещи, которые не анализируются в десятичной системе.

Coordinate[] result = segment 
.Split(';') 
.Select(s => s.Split(',')) 
.Select(BuildCoordinate) 
.ToArray(); 

Coordrinate BuildCoordinate(string[] coords) 
{ 
    if(coords.Length != 2) 
     return null; 

    return new Coordinate(double.Parse(a[0].Trim(), double.Parse(a[1]); 
} 
3

Вы можете сделать это:

public class GeoCoordinates { 
    public decimal Latitude { get; set; } 
    public decimal Longitude { get; set; } 

    public GeoCoordinates(string latLongPair) { 
    decimal lat, lng; 
    var parts = latLongPair.Split(new[] { ',' }); 
    if(decimal.TryParse(parts[0], out lat) && 
     decimal.TryParse(parts[1], out lng)) { 
     Latitude = lat; 
     Longitude = lng; 
    } else { 
     // you could set some kind of "ParseFailed" or "Invalid" property here 
    } 
    } 
} 

Затем вы можете создать коллекцию классов GeoCoordinate таким образом:

var coords = segment.Split(new[] {';'}).Select(x => new GeoCoordinates(x)); 
+0

Ты избил меня! :) – SouthShoreAK

+0

Хех ... StackOverflow может быть довольно гоночной, не правда ли? –

3

Вот 'несколько' хороший сниппет показ:

  • предварительно скомпилированный regexen
  • LINQ для анонимного типа проекции
  • Культуры известна (правильного) номер анализа и печатей

Вы хотели бы извлечь определенный код (например, парсинг чисел) в реальной жизни.

Посмотри live on Ideone.com.

using System; 
using System.Linq; 
using System.Text.RegularExpressions; 
using System.Globalization; 

namespace SODemo 
{ 
    class MainClass 
    { 
     private static readonly CultureInfo CInfo = CultureInfo.CreateSpecificCulture("en-US"); 

     public static void Main (string[] args) 
     { 
      string segment = "51.54398, -0.27585;51.55175, -0.29631;51.56233, -0.30369;51.57035, -0.30856;51.58157, -0.31672;51.59233, -0.3354"; 

      var re = new Regex(@"\s*(?<lat>[-+]?[0-9.]+),\s*(?<lon>[-+]?[0-9.]+)\s*;", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); 

      var locations = re.Matches(segment).Cast<Match>().Select(m => new 
      { 
       Lat = decimal.Parse(m.Groups["lat"].Value, CInfo), 
       Long = decimal.Parse(m.Groups["lon"].Value, CInfo), 
      }); 

      foreach (var l in locations) 
       Console.WriteLine(l); 
     } 
    } 
} 

Выход:

{ Lat = 51,54398, Long = -0,27585 } 
{ Lat = 51,55175, Long = -0,29631 } 
{ Lat = 51,56233, Long = -0,30369 } 
{ Lat = 51,57035, Long = -0,30856 } 
{ Lat = 51,58157, Long = -0,31672 } 
Смежные вопросы