2013-05-13 2 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 

мне нужно отсортировать этот .csv по 4-й колонке (IN_time) за счет увеличения времени (08:00:00, 08:00:01) и 6-й (In_Location) по алфавитному направлению (например, Восток, Север и т. Д.).

Пока мой код выглядит следующим образом:

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

+2

Во-первых, вы игнорируете возвращаемое значение 'string.Split' - это как если бы вы не вызывали его. Что вы ожидаете от этого? Во-вторых, я настоятельно рекомендую вам создать класс для представления всех значений в одной строке текста. Разбирайте каждую строку и добавьте ее в список как новый объект соответствующего типа. (Мы не можем сказать, какими должны быть эти данные, к сожалению, поэтому трудно дать примерное имя.) –

+0

Я бы использовал считыватель CSV (написанный кем-то еще), чтобы превратить данные в «Список ' (если это единственное использование, я скорее всего не буду его вводить). Затем я буду использовать 'IEnumerable.OrderBy' (который хорошо работает с составным упорядочением) и использовать сценарий CSV (написанный кем-то еще), чтобы выплевывать все обратно. Или, я бы использовал Excel: D – user2246674

ответ

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 является * длинным * способом от этого подходящего. –

+0

@JonSkeet расширил мой ответ, чтобы теперь он выглядел более полезным для OP –

+0

Правильно, это намного более полезно. Вы должны, вероятно, также упомянуть, что 'OrderBy' и' ThenBy' не будут сортироваться на месте ... –

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

+0

Вы можете суммировать значения в одном столбце, проверить обновленный ответ. –

0

Вы имеете дело с двумя различными проблемами.

Во-первых, заказав два столбца в C# может быть достигнуто с OrderBy, 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.

Смежные вопросы