Изменение таблицы данных

Я импортирую файл excel в таблицу данных (dtImport) и перестраиваю эти данные в другую таблицу данных (dtImportParsed).

Вот как выглядит эта таблица данных (dtImport), когда я впервые импортирую ее.

И вот как я пытаюсь изменить эту таблицу данных (dtImportParsed):



В настоящее время я выполняю это, используя несколько вложенных циклов for, но это занимает очень много времени. Например, лист с 36 столбцами и 4000 строк заполняется примерно за 30–40 минут. Есть ли альтернативный способ сделать это, который ускорит процесс?

Вот мой код:

for (int c = 2; c < dtImport.Columns.Count; c++) //for each date column
            {
                for (int r = 1; r < dtImport.Rows.Count; r++)
                {
                    if (dtImportParsed.Rows.Count == 0)
                    {
                        DataRow dataRowImport = dtImportParsed.NewRow();
                        dataRowImport["Date"] = dtImport.Columns[c].ColumnName.ToString().Trim();
                        dataRowImport["account_id"] = dtImport.Rows[r]["account_id"].ToString().Trim();
                        dataRowImport[dtImport.Rows[r]["Event Name"].ToString().Trim()] = dtImport.Rows[r][c].ToString().Trim();
                        dtImportParsed.Rows.Add(dataRowImport);
                    }
                    else
                    {
                        for (int i = 0; i < dtImportParsed.Rows.Count; i++)
                        {
                            if (dtImportParsed.Rows[i]["account_id"].ToString() == dtImport.Rows[r]["account_id"].ToString())
                            {
                                if (dtImportParsed.Rows[i]["Date"].ToString() == dtImport.Columns[c].ColumnName.ToString())
                                {
                                    dtImportParsed.Rows[i][dtImport.Rows[r]["Event Name"].ToString().Trim()] = dtImport.Rows[r][c].ToString().Trim();
                                    break;
                                }
                            }
                            else if (i == dtImportParsed.Rows.Count - 1)
                            {
                                DataRow dataRowImport = dtImportParsed.NewRow();
                                dataRowImport["Date"] = dtImport.Columns[c].ColumnName.ToString().Trim();
                                dataRowImport["account_id"] = dtImport.Rows[r]["account_id"].ToString().Trim();
                                dataRowImport[dtImport.Rows[r]["Event Name"].ToString().Trim()] = dtImport.Rows[r][c].ToString().Trim();
                                dtImportParsed.Rows.Add(dataRowImport);
                            }
                        }
                    }

                }
            }

Это не отвечает на вопрос, но решает проблему. Я не уверен, как вы выполняете импорт, но некоторые библиотеки Excel предоставляют доступ к функциям Excel при работе с файлом. Таким образом, можете ли вы выполнить сводную команду для файла Excel перед извлечением данных? Другой альтернативой может быть переход к базе данных и использование команды SQL Pivot.

Stephen Wrighton 19.02.2023 18:06

Привет, сводка в excel не поворачивает таблицу так, как мне нужно, к сожалению :(. Также нет доступа к базе данных

Jason Mills 19.02.2023 18:08
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Алгоритм, который вы используете для получения ожидаемого результата, слишком дорог! Он будет выполняться в порядке (c x r x i), где i > r, потому что в итоговую таблицу вводятся пустые поля; На самом деле это алгоритм O(n3)! Кроме того, вы предварительно формируете его на DataTable с помощью итерации DataRow, которые, вероятно, неэффективны для ваших требований.

Если ваш исходный набор данных невелик (как вы упомянули) и у вас нет ограничений по памяти, я предлагаю вам организовать ожидаемый набор данных в памяти с использованием структур данных на основе индексов. Что-то вроде этого:

var arrangeDragon = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();

Дракон входит! И съедает внутреннюю for.

for (int c = 2; c < dtImport.Columns.Count; c++) //for each date column
{
    for (int r = 1; r < dtImport.Rows.Count; r++)
    {
        // ...

        // instead of:     for (int i = 0; i < dtImportParsed.Rows.Count; i++) ...
        string date = dtImport.Columns[c].ColumnName.ToString().Trim();
        string accountId = dtImport.Rows[r]["account_id"].ToString();
        string eventName = dtImport.Rows [r]["Event Name"].ToString().Trim();

        if (!arrangeDragon.ContainsKey(date))
            arrangeDragon.Add(date, new Dictionary<string, Dictionary<string, string>>());

        if (!arrangeDragon[date].ContainsKey(accountId))
            arrangeDragon[date][accountId] = new Dictionary<string, string>();

        if (!arrangeDragon[date][accountId].ContainsKey(eventName))
            arrangeDragon[date][accountId][eventName] = dtImport.Rows[r][c].ToString().Trim();

        // ...
    }
}

Эти проверки будут выполняться за O (1) вместо O (i), поэтому общие накладные расходы уменьшатся до O (n2), что является характером итерационной таблицы :)

Также порядок получения O (1):

string data_field = arrangeDragon["1/1/2022"]["account1"]["Event1"];
Assert.AreEqual(data_field, "42");

Теперь вы можете один раз перебрать вложенные Dictionary и построить dtImportParsed.

Если ваш набор данных велик или памяти хоста мало, вам нужны другие решения, которые не являются вашей проблемой, как уже упоминалось;)

Удачи

Другие вопросы по теме