2013-05-13 72 views
-1

我有一個.csv文件,其中包含以下標題和示例行。按多個參數排序列表

AgentID,Profile,Avatar,In_Time,Out_Time,In_Location,Out_Location,Target_Speed(m/s),Distance_Traveled(m),Congested_Duration(s),Total_Duration(s),LOS_A_Duration(s),LOS_B_Duration(s),LOS_C_Duration(s),LOS_D_Duration(s),LOS_E_Duration(s),LOS_F_Duration(s) 
2177,DefaultProfile,DarkGreen_LowPoly,08:00:00,08:00:53,East12SubwayportalActor,EWConcourseportalActor,1.39653,60.2243,5.4,52.8,26.4,23,3.4,0,0,0 

我需要通過字母方向增加時間(08:00:00,8時00分01秒)和第六屆(In_Location)(例如東來此.csv由第4列(In_time的)排序,北等)。

到目前爲止,我的代碼如下所示:

List<string> list = new List<string>(); 
using (StreamReader reader = new StreamReader("JourneyTimes.csv")) 
{ 
    string line; 
    while ((line = reader.ReadLine()) != null) 
    { 
     line.Split(','); 
     list.Add(line); 
    } 

我在.csv讀取和使用逗號(沒有其他逗號所以這不是一個問題),把它分解。然後我將每行添加到列表中。我的問題是我如何排序兩個參數列表和.csv的標題。

我一直在尋找這個,我對編程相對比較陌生,這是我的第一個程序,所以我對我的知識缺乏表示歉意。

+2

您分割線('line.Split(',');')並丟棄結果。 – I4V 2013-05-13 20:27:16

+2

首先,你忽略了'string.Split'的返回值 - 就好像你沒有調用它。你期待它做什麼?其次,我強烈建議您創建一個類來表示一行文本中的所有值。解析每一行,並將其作爲適當類型的新對象添加到列表中。 (我們不能真正知道這些數據是什麼意思,不幸的是,所以很難給出一個樣本名稱。) – 2013-05-13 20:27:22

+0

我會使用CSV閱讀器(由其他人編寫)將數據轉換爲一個'List ' (如果這是我可能不會再輸入的唯一用法)。然後我會使用'IEnumerable.OrderBy'(它可以很好地處理複合排序),並使用CSV編寫器(由其他人編寫)將所有內容都吐出來。或者,我會使用Excel:D – user2246674 2013-05-13 20:28:32

回答

4

您可以使用LINQOrderBy/ThenBy

例如

listOfObjects.OrderBy (c => c.LastName).ThenBy (c => c.FirstName) 

但首先,你應該映射您CSV線的一些對象。 要映射CSV線對象,你可以預先設置一些類型的或動態創建

from line in File.ReadLines(fileName).Skip(1) //header 
let columns = line.Split(',') //really basic CSV parsing, consider removing empty entries and supporting quotes 
select new 
{ 
    AgentID = columns[0], 
    Profile = int.Parse(columns[1]), 
    Avatar = float.Parse(columns[2]) 
    //other properties 
} 

而且要知道,像許多其他LINQ的方法,這兩種使用deferred execution

+0

不是沒有更多的工作。從這個合適的角度來看,OP是一個很長的途徑。 – 2013-05-13 20:28:20

+0

@JonSkeet延長了我的回答,因此現在看起來對於OP – 2013-05-13 20:35:55

+0

更有幫助,對我來說這很有幫助。你應該也可以提到'OrderBy'和'ThenBy'不會被排序...... – 2013-05-13 20:36:38

0

你可以使用一個DataTable

var lines = File.ReadAllLines("test.csv"); 
DataTable dt = new DataTable(); 
var columNames = lines[0].Split(new char[] { ',' }); 
for (int i = 0; i < columNames.Length; i++) 
{ 
    dt.Columns.Add(columNames[i]); 
} 

for (int i = 1; i < lines.Length; i++) 
{ 
    dt.Rows.Add(lines[i].Split(new char[] { ',' })); 
} 

var rows = dt.Rows.Cast<DataRow>(); 
var result = rows.OrderBy(i => i["In_time"]) 
    .ThenBy(i => i["In_Location"]); 

// sum 
var sum = rows.Sum(i => Int32.Parse(i["AgentID"].ToString())); 
+0

這看起來很漂亮。分類後,我可以隨時將列操作應用於此嗎? 例如,我可以總結數據表中特定列的值嗎? – user2379217 2013-05-13 20:55:33

+0

您可以將一列中的值相加,檢查更新後的答案。 – 2013-05-13 21:03:46

0

您正在處理兩個不同的問題。

首先,訂貨在C#中的兩列可以排序依據來實現,ThenBy

public class SpreadsheetExample 
{ 
    public DateTime InTime { get; set; } 
    public string InLocation { get; set; } 

    public SpreadsheetExample(DateTime inTime, string inLocation) 
    { 
     InTime = inTime; 
     InLocation = inLocation; 
    } 

    public static List<SpreadsheetExample> LoadMockData() 
    { 
     int maxMock = 10; 
     Random random = new Random(); 
     var result = new List<SpreadsheetExample>(); 
     for (int mockCount = 0; mockCount < maxMock; mockCount++) 
     { 
      var genNumber = random.Next(1, maxMock); 
      var genDate = DateTime.Now.AddDays(genNumber); 
      result.Add(new SpreadsheetExample(genDate, "Location" + mockCount)); 
     } 

     return result; 
    } 
} 

internal class Class1 
{ 
    private static void Main() 
    { 
     var mockData = SpreadsheetExample.LoadMockData(); 
     var orderedResult = mockData.OrderBy(m => m.InTime).ThenBy(m => m.InLocation);//Order, ThenBy can be used to perform ordering of two columns 

     foreach (var item in orderedResult) 
     { 
      Console.WriteLine("{0} : {1}", item.InTime, item.InLocation); 
     } 
    } 
} 

現在你可以解決數據移入從Excel一類的第二個問題。 VSTO是你在找什麼。有很多examples在線。按照我上面發佈的示例。替換您的自定義類代替SpreadSheetExample