为了账号安全,请及时绑定邮箱和手机立即绑定

c# csv使用第三列对列表进行排序

c# csv使用第三列对列表进行排序

C#
慕工程0101907 2023-08-20 15:20:41
我有一个程序,可以使用 StreamReader 打开 CSV 文件,并根据 CSV 文件中的行数创建一个包含 4 列和行的表。这可以正常工作,就像创建以下输出一样:商品代码、商品描述、当前数量、订购时A0001,玩具车,4,有A0002,玩具卡车,1,无我将 CSV 文件中的所有数据保存在全局列表中,而不拆分每一行。当我创建表时,我使用“Split(',')”分割行,这在当时需要时工作。但是我不确定如何使用“当前计数”列从最大到最小重新排序整个列表。我已尝试以下操作,但在 Split(',') 上出现错误。public static class Globals{    public static List<string> items = new List<string>();}private void createTableWithOrder(int order){    for (int i = 0; i < Globals.items.; i++)    {         var values = Globals.items[i].Split(',');         if (order == 1)         {              values = Globals.items[i].OrderBy(itemDesc => itemDesc.Split(',')).ToList();         }    }}给出的错误如下:“char”不包含“Split”的定义,并且找不到接受“char”类型的第一个参数的扩展方法“Split”(您是否缺少 using 指令或程序集引用?)
查看完整描述

4 回答

?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

该OrderBy调用正在处理处字符串中的所有字符Globals.items[i]。这就是您看到当前错误的原因。为了对整个集合进行排序,需要对整个列表进行排序,例如:


var values = Globals.items.Select(line => line.Split(',')); // Select columns for all rows

var orderedListOfValues = values

    .OrderByDescending(cols => int.TryParse(cols[2].Trim(), out var order) ? order : int.MaxValue); // Sort  by count as an integer

请注意,在上面的示例中,对非数字值(例如标题)进行排序将使用整数的最大值。根据预期的结果,这些结果可以合并回字符串列表中以供演示:


var orderedItems = string.Join(",", orderedListOfValues)

干杯!


查看完整回答
反对 回复 2023-08-20
?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

您存储列表的方式不会帮助您生成具有排序功能的表。要解决您的问题,List<string>您应该使用这些模型创建列表来创建模型(IItem 接口和 Item 类)。然后在渲染表格之前,您可以根据您喜欢的任何列对列表进行排序。

List<IItem> items = new List<Item>();
items.Add({itemCode: excelData.itemCode , itemDescription: excelData.itemDescription,itemCount: excelData.itemCount, orderCount:excelData.orderCount});
List<IItem> itemsToCreateTable = items.OrderBy(o=>o.itemCount).ToList();


查看完整回答
反对 回复 2023-08-20
?
哆啦的时光机

TA贡献1779条经验 获得超6个赞

不是直接回答你的问题。但我认为您正在编写已经可以免费使用的代码。

我强烈建议您使用nuget 包 CSV Helper。它接受任何文本流、字符串、文本阅读器等,并将 CSV 文件转换为您期望类型的 IEnumerable。它可以在有或没有包含列的标题行的情况下使用

class MyItem

{

    public string Code {get; set;}

    public string Description {get; set;}

    public int Count {get; set;}

    public bool OnOrder {get; set;}

}

从 CSV 文件中获取所有 MyItems:


string myCsvFileName = ...

using (TextReader reader = new StreamReader(myCsvFileName))

{

    using (var csv = new CsvReader(reader))

    {    

        IEnumerable<MyItem> items = reader.GetRecords<MyItem>();


        // you can do any Linq with this:

        var allItems = items.ToList();


        // or if you only need some records:

        var unAvailableItems = items.Where(item => item.Count == 0);

    }

}

阅读链接以了解如果您有特殊分隔符、标题行或其他任何内容该怎么办。它是高度可配置的。


查看完整回答
反对 回复 2023-08-20
?
jeck猫

TA贡献1909条经验 获得超7个赞

目前尚不清楚为什么您不简单地为文件中的项目创建一个“类”。通过“类别”,您可以以任何您选择的方式和多种方式对项目进行排序。此外,您想要排序的列(当前计数)似乎是数字。如果您将数字排序为strings,您将得到所有 1 在一起、2 在一起等。例如,它看起来像这样。

1

10

100

2

20

3

4 …

您将无法使用字符串获得正确的数字排序顺序。因此,您必须按数字而不是字符串对列进行排序才能获得正确的数字顺序。使用类背后的想法是它可以让您完全控制排序。如果你创建一个List并且Item该类Item实现了该IComparable接口,则可以用一行代码完成排序......Items.Sort().

下面是上述内容的示例。首先是“类”Item来保存文件中的对象。它仅包含此示例所需的属性,即CompareTo调用时将使用的方法Items.Sort().

public class Item : IComparable {


  public string Code { get; set; }

  public string Description { get; set; }

  public int Count { get; set; }

  public bool OnOrder { get; set; }


  public Item(string code, string description, int count, bool onOrder) {

    Code = code;

    Description = description;

    Count = count;

    OnOrder = onOrder;

  }


  public int CompareTo(object obj) {

    Item that = (Item)obj;

    return Count.CompareTo(that.Count);

  } 

}

Item下面是使用该类按“当前计数”列对列表进行排序的示例。ADataGridView用于显示排序列表。


List<Item> Items;


public Form1() {

  InitializeComponent();

}


private void Form1_Load(object sender, EventArgs e) {

  Items = GetData();

  Items.Sort();

  dataGridView1.DataSource = Items;

}


private List<Item> GetData() {

  List<Item> items = new List<Item>();

  Item newItem;

  string line;

  using (StreamReader sr = new StreamReader(@"D:\Test\Test22.csv")) {

    while ((line = sr.ReadLine()) != null) {

      if ((newItem = GetItemFromString(line)) != null) {

        items.Add(newItem);

      }

    }

  }

  return items;

}


private Item GetItemFromString(string itemString) {

  string[] splitArray = itemString.Split(',');

  bool onOrder;

  int count = 0;

  if (splitArray.Length >= 4) {

    int.TryParse(splitArray[2].Trim(), out count);

    if (splitArray[3].Trim() == "Yes")

      onOrder = true;

    else

      onOrder = false;

    return new Item(splitArray[0].Trim(), splitArray[1].Trim(), count, onOrder);

  }

  return null;

}

希望这可以帮助。


查看完整回答
反对 回复 2023-08-20
  • 4 回答
  • 0 关注
  • 197 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信