2017-07-03 18 views
4

我的大腦不工作,我試圖讓事情比我想象的要真實,我需要另一雙眼睛。我曾經在一個文本文件中的以下創建一個JSON字符串的問題

|TS|170702/2300|170703/0503|42.80 -102.64 39.76 -102.64 39.44 -99.37 42.48 -99.37 
|TS|170703/0505|170703/0905|40.22 -97.30 38.63 -97.30 38.19 -101.03 39.78 -101.03 

上面有哪些手段?(| watchtype | watchstart | watchend |經/緯對)

我遇到的問題是我需要採用EACH ROW(可能爲0或可能爲100+),並在地圖上創建多邊形以標記這些暴風雨表的位置。我目前有以下。

模型

public class WatchPolygons 
{ 
    public string WatchType { get; set; } 
    public string WatchStart { get; set; } 
    public string WatchEnd { get; set; } 
    public List<lat_longPairs> Lat_Long_Pairs {get; set;} 
} 

public class lat_longPairs 
{ 
    public decimal latitude { get; set; } 
    public decimal longitude { get; set; } 
} 

控制器

public JsonResult GetWatchPath() 
{ 
    var watchFilePaths = ConfigurationManager.AppSettings["watchFilePath"]; 
    return Json(Directory.GetFiles(Server.MapPath(watchFilePaths), "current*.txt"), JsonRequestBehavior.AllowGet); 
} 

[HttpGet] 
public ActionResult GetWatchData(string watchPath) 
{ 
    var stringData = new List<string>(); 
    using (var reader = new StreamReader(watchPath)) 
    { 
     while (!reader.EndOfStream) 
     { 
      var data = reader.ReadLine().Trim(); 

      if (!string.IsNullOrEmpty(data)) 
       stringData.Add(data); 
     } 

    } 

    return Json((from item in stringData 
       select item.Split(new char [] { '|' }, StringSplitOptions.RemoveEmptyEntries) 
       into rawData 
       select new WatchPolygons 
       { 
        WatchType = rawData[0], 
        WatchStart = rawData[1], 
        WatchEnd = rawData[2] 
       }).ToList(), JsonRequestBehavior.AllowGet); 
} 

我知道我錯過了latlong pairs = rawData。我沒有在代碼中使用它,因爲在模型中它是一個列表,我不能輕鬆地將列表轉換爲我需要的字符串。

我錯過了什麼?我相信我需要仔細閱讀每一行,然後閱讀每個組以獲得經緯度對。只是不確定。

回答

4

您只需要解析rawData[3],其中包含空格分隔的經緯度對的字符串。這是一個天真的實施將打破當輸入字符串不包含對數字的或在當前區域設置不使用點作爲小數分隔符:

private static List<lat_longPairs> ParseLatLon(string input) 
{ 
    var numbers = input.Split(new [] { " " }, StringSplitOptions.RemoveEmptyEntries) 
         .Select(i => decimal.Parse(i)) 
         .ToArray(); 

    var latLonPairs = new List<lat_longPairs>(); 

    for (int i = 0; i < numbers.Length; i += 2) 
    { 
     latLonPairs.Add(new lat_longPairs 
     { 
      latitude = numbers[i], 
      longitude = numbers[i + 1], 
     }); 
    } 

    return latLonPairs; 
} 

然後從那裏您正在投射叫它多邊形:

select new WatchPolygons 
{ 
    WatchType = rawData[0], 
    WatchStart = rawData[1], 
    WatchEnd = rawData[2], 
    Lat_Long_Pairs = ParseLatLon(rawData[3]) 
} 

您可能希望將解析代碼也從控制器中移出,並移入其自己的類中。

+0

沒有理由不使用'decimal.Parse(i,NumberFormatInfo.InvariantInfo)'來確保在所有文化中一致的解析。 – dbc

+0

這工作完美。謝謝! – bradoxbl

+0

@dbc作爲文化敏感小數點分隔符的點只是解析此字符串時的一對潛在問題之一,正如本答案中所述。它需要更多的錯誤處理。我想展示解決這個問題的模式,而不是一個完整的,經過充分測試和強大的解決方案,這是由讀者決定的。 – CodeCaster

0

您可以使用GroupBy,因爲兩組座標。

 var str = "|TS|170702/2300|170703/0503|42.80 -102.64 39.76 -102.64 39.44 -99.37 42.48 -99.37"; 
     int itemsInGroup = 2; 
     var pairs = str.Split('|')[4].Split(' '). 
        // Give each set of coordinate a group number. 
        Select((n, i) => new { GroupNumber = i/itemsInGroup, Number = n }). 
        GroupBy(n => n.GroupNumber). 
        Select(g => 
        { 
         var coordinate = g.Select(n => n.Number).ToList(); 
         return new lat_longPairs 
         { 
          latitude = decimal.Parse(coordinate[0], NumberFormatInfo.InvariantInfo), 
          longitude = decimal.Parse(coordinate[1], NumberFormatInfo.InvariantInfo), 
         }; 
     });