AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78522547
Accepted
user366312
user366312
Asked: 2024-05-23 18:41:37 +0800 CST2024-05-23 18:41:37 +0800 CST 2024-05-23 18:41:37 +0800 CST

Como posso classificar os arquivos CSV por colunas como vemos nas planilhas?

  • 772

Suponha que eu tenha o seguinte arquivo CSV:

Column1,Column2,Column3
C,3,1
B,2,2
A,3,3
C,3,10
B,2,20
A,2,30
C,3,100
B,1,200
A,1,300

Eu quero resolver isso

  • Primeiro pela Coluna1
  • Segundo pela Coluna2
  • Terceiro pela Coluna3

Portanto o resultado deverá ser o seguinte:

Column1,Column2,Column3
A,1,300
A,2,30
A,3,3
B,1,200
B,2,2
B,2,20
C,3,1
C,3,10
C,3,100

Para classificar CSV por colunas em ordem crescente/decrescente, criei a seguinte classe:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace SikorskiLibMemoryLess
{
    public enum SortTypeEnum
    {
        Ascending,
        Descending
    }

    public static class ListExtensions
    {
        public static string ToCommaSeparatedString(this List<string> list)
        {
            if (list == null || !list.Any())
            {
                return string.Empty;
            }

            return string.Join(",", list);
        }
    }

    public class CSVSorter
    {
        public List<string> Header { get; private set; }
        public List<List<string>> Data { get; private set; }

        public CSVSorter()
        {
            Data = new List<List<string>>();
        }

        public void LoadCSV(string filePath, bool hasHeader = true)
        {
            using (StreamReader sr = new StreamReader(filePath))
            {
                string line;
                bool isFirstLine = true;

                while ((line = sr.ReadLine()) != null)
                {
                    List<string> columns = line.Split(',').Select(col => string.IsNullOrWhiteSpace(col) ? null : col).ToList();

                    if (isFirstLine && hasHeader)
                    {
                        Header = columns;
                        isFirstLine = false;
                    }
                    else
                    {
                        Data.Add(columns);
                        if (isFirstLine)
                        {
                            isFirstLine = false;
                            if (!hasHeader)
                            {
                                Header = Enumerable.Range(1, columns.Count).Select(i => "Column" + i).ToList();
                            }
                        }
                    }
                }
            }
        }

        public void LoadCSV(string fileName, string fileDir, bool hasHeader = true)
        {
            string filePath = Path.Combine(fileDir, fileName);
            LoadCSV(filePath, hasHeader);
        }

        public void LoadCSV(IEnumerable<List<string>> csvData, bool hasHeader = true)
        {
            bool isFirstLine = true;

            foreach (var columns in csvData)
            {
                var processedColumns = columns.Select(col => string.IsNullOrWhiteSpace(col) ? null : col).ToList();
                if (isFirstLine && hasHeader)
                {
                    Header = processedColumns;
                    isFirstLine = false;
                }
                else
                {
                    Data.Add(processedColumns);
                    if (isFirstLine)
                    {
                        isFirstLine = false;
                        if (!hasHeader)
                        {
                            Header = Enumerable.Range(1, processedColumns.Count).Select(i => "Column" + i).ToList();
                        }
                    }
                }
            }
        }

        public void Sort(int[] columns, SortTypeEnum ascendingOrDescending)
        {
            try
            {
                IOrderedEnumerable<List<string>> sortedData = null;

                if (ascendingOrDescending == SortTypeEnum.Ascending)
                {
                    sortedData = Data.OrderBy(row => GetColumnValueSafe(row, columns[0]));
                    for (int i = 1; i < columns.Length; i++)
                    {
                        sortedData = sortedData.ThenBy(row => GetColumnValueSafe(row, columns[i]));
                    }
                }

                Data = sortedData.ToList();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error during sorting: {ex.Message}");
                Console.WriteLine(ex.StackTrace);
            }
        }

        private string GetColumnValueSafe(List<string> row, int columnIndex)
        {
            return columnIndex < row.Count ? row[columnIndex] : null;
        }

        public IEnumerable<List<string>> Get()
        {
            yield return Header;
            foreach (var row in Data)
            {
                yield return row;
            }
        }

        public void SaveCSV(string filePath)
        {
            using (StreamWriter sw = new StreamWriter(filePath))
            {
                // Write the header
                sw.WriteLine(string.Join(",", Header));

                // Write the data rows
                foreach (var row in Data)
                {
                    sw.WriteLine(string.Join(",", row.Select(col => col ?? "")));
                }
            }
        }

        public void SaveCSV(string fileName, string fileDir)
        {
            string filePath = Path.Combine(fileDir, fileName);
            SaveCSV(filePath);
        }
    }

    class Program
    {
        static void Main()
        {
            // Example usage for CSV with potential missing data
            CSVSorter sorter = new CSVSorter();
            sorter.LoadCSV(@"C:\git\rouse_data~~\[PENULTIMATE]\OUTPUT_CSV\input.csv", true); // Adjust path as needed
            sorter.Sort(new int[] { 0,1,2 }, SortTypeEnum.Ascending); // Sort by the second column (e.g., particleVolume) in ascending order
            sorter.SaveCSV(@"C:\git\rouse_data~~\[PENULTIMATE]\OUTPUT_CSV\sorted___input.csv");

            // Display sorted data
            foreach (var row in sorter.Get())
            {
                Console.WriteLine(string.Join(", ", row));
            }
        }
    }
}

Esta aula não está me dando o resultado desejado.

Column1,Column2,Column3
C,3,1
B,2,2
A,3,3
C,3,10
B,2,20
A,2,30
C,3,100
B,1,200
A,1,300

Existe alguma biblioteca de código aberto para classificar dados CSV por colunas?

c#
  • 1 1 respostas
  • 29 Views

1 respostas

  • Voted
  1. Best Answer
    Tim Schmelter
    2024-05-23T19:53:11+08:002024-05-23T19:53:11+08:00

    No seu código de exemplo você não usa o parâmetro desejado new int[]{0, 1, 2}(editar: agora você corrigiu na sua pergunta), pois deseja ordenar pela primeira coluna e depois pelas demais. Se você fizer isso, você receberá um IndexOutOfRangeException(na sua captura). A razão para isso é um bug sutil no seu loop:

    for (int i = 1; i < columns.Length; i++)
    {
        sortedData = sortedData.ThenBy(row => GetColumnValueSafe(row, columns[i]));
    }
    

    O Resharper diria aqui: "a variável capturada foi modificada no escopo externo" e isso está causando isso. Então a correção é fácil, crie uma cópia dessa variável;

    for (int i = 1; i < columns.Length; i++)
    {
        int colIndex = i;
        sortedData = sortedData.ThenBy(row => GetColumnValueSafe(row, columns[colIndex]));
    }
    

    outra opção - melhor - é usar a foreach(C # 5 corrigiu):

    foreach (int column in columns)
    {
        sortedData = sortedData.ThenBy(row => GetColumnValueSafe(row, column));
    }
    

    Veja esta resposta para mais detalhes: Existe uma razão para a reutilização da variável pelo C# em um foreach?

    Agora você obtém o resultado desejado, pois todo o resto parece funcionar corretamente:

    Column1,Column2,Column3
    A,1,300
    A,2,30
    A,3,3
    B,1,200
    B,2,2
    B,2,20
    C,3,1
    C,3,10
    C,3,100
    
    • 1

relate perguntas

  • Polly DecorrelatedJitterBackoffV2 - como calcular o tempo máximo necessário para concluir todas as novas tentativas?

  • Wpf. Role o DataGrid dentro do ScrollViewer

  • A pontuação que ganhei na página do jogo com .NET MAUI MVVM não é visível em outras páginas. Como posso manter os dados de pontuação no dispositivo local

  • Use a hierarquia TreeView com HierarchicalDataTemplate de dentro de um DataTemplate

  • Como posso melhorar essa interface de validação no .NET?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve