如何使用 .csv 文件中的数据添加到 C# 中的对象列表<>?
How can I add to a List<> of objects in C# with data from a .csv file?
我使用 productdetails.csv 文件中的信息创建了一个对象列表<>,我必须使用 salesdata.csv 中的信息更新该列表<>,我目前存储在一个数组中(5 int销售数量的数字),但我不知道该怎么做。我在 Product Class 中添加了另一个构造函数,认为也许我可以创建一个包含 'WeeklySales' 属性 的新对象列表<>...不幸的是我找不到任何其他类似问题的启示。在此先感谢您对这个主题的任何启发。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace q6._2
{
class Program
{
static void Main(string[] args)
{
string fileName = GetDataDirectory() + "\data\salesdata.csv";
string[] salesDetails = File.ReadAllLines(fileName);
string[] salesCol = new string[2];
for (int i = 1; i < salesDetails.Length; i++)
{
string currentLine = salesDetails[i];
salesCol = currentLine.Split(',');
string salesQuant = salesCol[1];
}
Console.ReadLine();
}
public static string GetDataDirectory()
{
string path = Directory.GetCurrentDirectory();
char[] removeSequence = { 'b', 'i', 'n', '\', 'D', 'e', 'b', 'u', 'g' };
string newPath = path.TrimEnd(removeSequence);
return newPath;
}
public static List<Product> ReadProductFile()
{
string fileName = GetDataDirectory() + "\data\productdetails.csv";
string[] productDetails = File.ReadAllLines(fileName);
string[] lineDetails = new string[5];
List<Product> productObj = new List<Product>();
for (int i = 1; i < productDetails.Length; i++)
{
lineDetails = productDetails[i].Split(',');
Product newProduct = new Product(lineDetails[0], lineDetails[1], lineDetails[2], Convert.ToDecimal(lineDetails[3]), Convert.ToInt32(lineDetails[4]));
productObj.Add(newProduct);
}
return productObj;
}
}
class Product
{
public string ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int StockAvailable { get; set; }
public int WeeklySales { get; set; }
public Product(string id, string name, string description, decimal price, int stockavailable)
{
ID = id;
Name = name;
Description = description;
Price = price;
StockAvailable = stockavailable;
}
public Product(string id, string name, string description, decimal price, int stockavailable, int weeklysales)
{
ID = id;
Name = name;
Description = description;
Price = price;
StockAvailable = stockavailable;
WeeklySales = weeklysales;
}
}
}
假设您的 salesdata.csv
的每一行中都有 ProductID。从问题中不清楚 - 是否如此。顺便说一下 - 它 应该 有那个 ProductID,因为我看不出你如何找到要更新的产品。
好的,您已经阅读了来自 salesdata
的一行 - 现在您需要在您的列表中找到对应的产品。这里出现了一些问题,因为 List
本身并不是一个很好的数据结构 - 你必须遍历整个列表才能找到具体的产品。
因此最好将 List<Product>
更改为 Dictionary<string, Product>
并假设字典键为 Product.ID
并填充它。在这种情况下,您将能够在 O(1) 时间内找到您的产品并更新其 WeeklySales,如:
for (int i = 1; i < salesDetails.Length; i++)
{
string currentLine = salesDetails[i];
salesCol = currentLine.Split(',');
string productID = salesCol[some_column_fromCSV];
your_products_dictionary[productID].WeeklySales = Convert.ToInt(salesCol[1]);
}
请注意这是伪代码,在这里我不关心可能的空引用等等。
另请注意 - 通过 File.ReadAllLines
读取 csv 文件的所有内容然后将其存储在数组中可能不是一个好主意。因为文件可能非常大,您可能 运行 内存不足。相反,您可以打开此文件并使用 TextReader Open
和 ReadLine
方法逐行读取。
这应该是答案。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace q6._2
{
class Program
{
static void Main(string[] args)
{
// ReadProductFile() <- fills all the
List<Product> productContents = ReadProductFile();
ReadSalesAndMergeWithProducts(ref productContents);
foreach (Product p in productContents)
{
Console.WriteLine(p.ToString());
}
Console.ReadLine();
}
private static void ReadSalesAndMergeWithProducts(ref List<Product> productContents)
{
string[] salesDetails = File.ReadAllLines(GetDataDirectory() + "\data\salesdata.csv");
int smallestNr = GetSmallestOfTwo(salesDetails.Length, productContents.Count);
for (int i = 1; i < smallestNr; i++)
{
productContents.ElementAt(i).WeeklySales = Convert.ToInt32(salesDetails[i].Split(',')[1]);
}
}
/// <summary>
/// shortend GetDataDirectory
/// </summary>
/// <returns></returns>
public static string GetDataDirectory()
{
return System.IO.Directory.GetCurrentDirectory().Replace("bin\Debug", "");
}
/// <summary>
/// ReadProductFile
/// </summary>
/// <returns>List<</returns>
public static List<Product> ReadProductFile()
{
// remove the filename string and directly pass it to the read all lines
string[] productDetails = File.ReadAllLines(GetDataDirectory() + "\data\productdetails.csv");
// no need to classify the size here since it will return from product details. (no harm though)
string[] lineDetails;// = new string[5];
// create a new product object
List<Product> productObj = new List<Product>();
// loop over the product details
for (int i = 1; i < productDetails.Length; i++)
{
// split on comma char
lineDetails = productDetails[i].Split(',');
// create new product
Product newProduct = new Product(lineDetails[0], lineDetails[1], lineDetails[2], Convert.ToDecimal(lineDetails[3]), Convert.ToInt32(lineDetails[4]));
// add product to list
productObj.Add(newProduct);
}
// return List<Product>
return productObj;
}
/// <summary>
/// GetSmallestOfTwo
/// </summary>
/// <param name="a">int</param>
/// <param name="b">int</param>
/// <returns>int</returns>
public static int GetSmallestOfTwo(int a, int b)
{
return (a <= b) ? a : b;
}
}
/// <summary>
/// Product class
/// </summary>
class Product
{
public string ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int StockAvailable { get; set; }
public int WeeklySales { get; set; }
public Product(string id, string name, string description, decimal price, int stockavailable)
{
ID = id;
Name = name;
Description = description;
Price = price;
StockAvailable = stockavailable;
}
public Product(string id, string name, string description, decimal price, int stockavailable, int weeklysales)
{
ID = id;
Name = name;
Description = description;
Price = price;
StockAvailable = stockavailable;
WeeklySales = weeklysales;
}
public String ToString()
{
return "ID: " + ID + " Name: " + Name + " Description: " + Description +
" Price:" + Price + "StockAvailable: " + StockAvailable + " WeeklySales: " + WeeklySales;
}
}
}
我使用 productdetails.csv 文件中的信息创建了一个对象列表<>,我必须使用 salesdata.csv 中的信息更新该列表<>,我目前存储在一个数组中(5 int销售数量的数字),但我不知道该怎么做。我在 Product Class 中添加了另一个构造函数,认为也许我可以创建一个包含 'WeeklySales' 属性 的新对象列表<>...不幸的是我找不到任何其他类似问题的启示。在此先感谢您对这个主题的任何启发。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace q6._2
{
class Program
{
static void Main(string[] args)
{
string fileName = GetDataDirectory() + "\data\salesdata.csv";
string[] salesDetails = File.ReadAllLines(fileName);
string[] salesCol = new string[2];
for (int i = 1; i < salesDetails.Length; i++)
{
string currentLine = salesDetails[i];
salesCol = currentLine.Split(',');
string salesQuant = salesCol[1];
}
Console.ReadLine();
}
public static string GetDataDirectory()
{
string path = Directory.GetCurrentDirectory();
char[] removeSequence = { 'b', 'i', 'n', '\', 'D', 'e', 'b', 'u', 'g' };
string newPath = path.TrimEnd(removeSequence);
return newPath;
}
public static List<Product> ReadProductFile()
{
string fileName = GetDataDirectory() + "\data\productdetails.csv";
string[] productDetails = File.ReadAllLines(fileName);
string[] lineDetails = new string[5];
List<Product> productObj = new List<Product>();
for (int i = 1; i < productDetails.Length; i++)
{
lineDetails = productDetails[i].Split(',');
Product newProduct = new Product(lineDetails[0], lineDetails[1], lineDetails[2], Convert.ToDecimal(lineDetails[3]), Convert.ToInt32(lineDetails[4]));
productObj.Add(newProduct);
}
return productObj;
}
}
class Product
{
public string ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int StockAvailable { get; set; }
public int WeeklySales { get; set; }
public Product(string id, string name, string description, decimal price, int stockavailable)
{
ID = id;
Name = name;
Description = description;
Price = price;
StockAvailable = stockavailable;
}
public Product(string id, string name, string description, decimal price, int stockavailable, int weeklysales)
{
ID = id;
Name = name;
Description = description;
Price = price;
StockAvailable = stockavailable;
WeeklySales = weeklysales;
}
}
}
假设您的 salesdata.csv
的每一行中都有 ProductID。从问题中不清楚 - 是否如此。顺便说一下 - 它 应该 有那个 ProductID,因为我看不出你如何找到要更新的产品。
好的,您已经阅读了来自 salesdata
的一行 - 现在您需要在您的列表中找到对应的产品。这里出现了一些问题,因为 List
本身并不是一个很好的数据结构 - 你必须遍历整个列表才能找到具体的产品。
因此最好将 List<Product>
更改为 Dictionary<string, Product>
并假设字典键为 Product.ID
并填充它。在这种情况下,您将能够在 O(1) 时间内找到您的产品并更新其 WeeklySales,如:
for (int i = 1; i < salesDetails.Length; i++)
{
string currentLine = salesDetails[i];
salesCol = currentLine.Split(',');
string productID = salesCol[some_column_fromCSV];
your_products_dictionary[productID].WeeklySales = Convert.ToInt(salesCol[1]);
}
请注意这是伪代码,在这里我不关心可能的空引用等等。
另请注意 - 通过 File.ReadAllLines
读取 csv 文件的所有内容然后将其存储在数组中可能不是一个好主意。因为文件可能非常大,您可能 运行 内存不足。相反,您可以打开此文件并使用 TextReader Open
和 ReadLine
方法逐行读取。
这应该是答案。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace q6._2
{
class Program
{
static void Main(string[] args)
{
// ReadProductFile() <- fills all the
List<Product> productContents = ReadProductFile();
ReadSalesAndMergeWithProducts(ref productContents);
foreach (Product p in productContents)
{
Console.WriteLine(p.ToString());
}
Console.ReadLine();
}
private static void ReadSalesAndMergeWithProducts(ref List<Product> productContents)
{
string[] salesDetails = File.ReadAllLines(GetDataDirectory() + "\data\salesdata.csv");
int smallestNr = GetSmallestOfTwo(salesDetails.Length, productContents.Count);
for (int i = 1; i < smallestNr; i++)
{
productContents.ElementAt(i).WeeklySales = Convert.ToInt32(salesDetails[i].Split(',')[1]);
}
}
/// <summary>
/// shortend GetDataDirectory
/// </summary>
/// <returns></returns>
public static string GetDataDirectory()
{
return System.IO.Directory.GetCurrentDirectory().Replace("bin\Debug", "");
}
/// <summary>
/// ReadProductFile
/// </summary>
/// <returns>List<</returns>
public static List<Product> ReadProductFile()
{
// remove the filename string and directly pass it to the read all lines
string[] productDetails = File.ReadAllLines(GetDataDirectory() + "\data\productdetails.csv");
// no need to classify the size here since it will return from product details. (no harm though)
string[] lineDetails;// = new string[5];
// create a new product object
List<Product> productObj = new List<Product>();
// loop over the product details
for (int i = 1; i < productDetails.Length; i++)
{
// split on comma char
lineDetails = productDetails[i].Split(',');
// create new product
Product newProduct = new Product(lineDetails[0], lineDetails[1], lineDetails[2], Convert.ToDecimal(lineDetails[3]), Convert.ToInt32(lineDetails[4]));
// add product to list
productObj.Add(newProduct);
}
// return List<Product>
return productObj;
}
/// <summary>
/// GetSmallestOfTwo
/// </summary>
/// <param name="a">int</param>
/// <param name="b">int</param>
/// <returns>int</returns>
public static int GetSmallestOfTwo(int a, int b)
{
return (a <= b) ? a : b;
}
}
/// <summary>
/// Product class
/// </summary>
class Product
{
public string ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int StockAvailable { get; set; }
public int WeeklySales { get; set; }
public Product(string id, string name, string description, decimal price, int stockavailable)
{
ID = id;
Name = name;
Description = description;
Price = price;
StockAvailable = stockavailable;
}
public Product(string id, string name, string description, decimal price, int stockavailable, int weeklysales)
{
ID = id;
Name = name;
Description = description;
Price = price;
StockAvailable = stockavailable;
WeeklySales = weeklysales;
}
public String ToString()
{
return "ID: " + ID + " Name: " + Name + " Description: " + Description +
" Price:" + Price + "StockAvailable: " + StockAvailable + " WeeklySales: " + WeeklySales;
}
}
}