Преобразовать универсальный Список / Счетный к DataTable?

Мы можем использовать mutate_at из dplyr

library(dplyr)
df %>%
  mutate_at(vars(c("x1", "x2")), funs(replace(., y == 0, NA)))

#   y x1 x2 x3
#   1 NA  1  9
#2  0 NA NA  5
#3  1  4  4  2
#4  1  7  7  4
#5  0 NA NA  7
#6  0 NA NA  2
#7  1  2 NA  5
#8  0 NA NA  8
#9  1  3  3  2
#10 0 NA NA  2
243
задан Simon Martin 2 June 2014 в 22:33
поделиться

5 ответов

Вот хорошее обновление 2013 года с помощью [1 111] FastMember от NuGet:

IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data)) {
    table.Load(reader);
}

Это использует метапрограммирование FastMember API для максимальной производительности. Если Вы хотите ограничить его конкретными участниками (или осуществлять порядок), то можно сделать это также:

IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) {
    table.Load(reader);
}

Редактор Скидка / претендент: FastMember является проектом Marc Gravell. Его золотые и настоящие мухи!

<час>

Да, это - в значительной степени полная противоположность [1 112] этот один; отражение было бы достаточно - или если Вам нужно более быстрый, HyperDescriptor в 2,0, или возможно Expression в 3,5. На самом деле, HyperDescriptor должно быть более, чем соответствующим.

, Например:

// remove "this" if not on C# 3.0 / .NET 3.5
public static DataTable ToDataTable<T>(this IList<T> data)
{
    PropertyDescriptorCollection props =
        TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    for(int i = 0 ; i < props.Count ; i++)
    {
        PropertyDescriptor prop = props[i];
        table.Columns.Add(prop.Name, prop.PropertyType);
    }
    object[] values = new object[props.Count];
    foreach (T item in data)
    {
        for (int i = 0; i < values.Length; i++)
        {
            values[i] = props[i].GetValue(item);
        }
        table.Rows.Add(values);
    }
    return table;        
}

Теперь с одной строкой можно сделать это многими много раз быстрее, чем отражение (путем включения HyperDescriptor для типа объекта T).

<час>

запрос производительности ре редактирования; вот тестовая буровая установка с результатами:

Vanilla 27179
Hyper   6997

я подозреваю, что узкое место сместилось от членского доступа до [1 110] производительность... Я сомневаюсь, что Вы улучшитесь очень относительно этого...

код:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
public class MyData
{
    public int A { get; set; }
    public string B { get; set; }
    public DateTime C { get; set; }
    public decimal D { get; set; }
    public string E { get; set; }
    public int F { get; set; }
}

static class Program
{
    static void RunTest(List<MyData> data, string caption)
    {
        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
        GC.WaitForPendingFinalizers();
        GC.WaitForFullGCComplete();
        Stopwatch watch = Stopwatch.StartNew();
        for (int i = 0; i < 500; i++)
        {
            data.ToDataTable();
        }
        watch.Stop();
        Console.WriteLine(caption + "\t" + watch.ElapsedMilliseconds);
    }
    static void Main()
    {
        List<MyData> foos = new List<MyData>();
        for (int i = 0 ; i < 5000 ; i++ ){
            foos.Add(new MyData
            { // just gibberish...
                A = i,
                B = i.ToString(),
                C = DateTime.Now.AddSeconds(i),
                D = i,
                E = "hello",
                F = i * 2
            });
        }
        RunTest(foos, "Vanilla");
        Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(
            typeof(MyData));
        RunTest(foos, "Hyper");
        Console.ReadLine(); // return to exit        
    }
}
309
ответ дан Community 23 November 2019 в 03:10
поделиться

Чтобы преобразовать общий список в таблицу данных, вы можете использовать DataTableGenerator

Эта библиотека позволяет преобразовывать ваш список в таблицу данных с многофункциональностью, например

  • Перевести заголовок таблицы данных
  • указать столбец для отображения
1
ответ дан 23 November 2019 в 03:10
поделиться

Ответ 2019 года при использовании.NET Core - использует библиотека Nuget ToDataTable . Преимущества:

Правовая оговорка - я - автор производительности ToDataTable

- я охватываю приблизительно Сравнительный тест .NET тесты и включал их в ToDataTable repo. Результаты были следующие:

Создание 100 000 Таблиц данных строки:

                           MacOS         Windows
Reflection                 818.5 ms      818.3 ms
FastMember from           1105.5 ms      976.4 ms
 Mark's answer
Improved FastMember        524.6 ms      456.4 ms
ToDataTable                449.0 ms      376.5 ms

метод FastMember, предложенный в , ответ Marc , казалось, работал хуже, чем ответ Mary's , который использовал отражение, но я прокрутил другой метод использование FastMember TypeAccessor, и это работало намного лучше. Тем не менее, пакет ToDataTable превзошел партию по характеристикам.

1
ответ дан 23 November 2019 в 03:10
поделиться

try this

public static DataTable ListToDataTable<T>(IList<T> lst)
{

    currentDT = CreateTable<T>();

    Type entType = typeof(T);

    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entType);
    foreach (T item in lst)
    {
        DataRow row = currentDT.NewRow();
        foreach (PropertyDescriptor prop in properties)
        {

            if (prop.PropertyType == typeof(Nullable<decimal>) || prop.PropertyType == typeof(Nullable<int>) || prop.PropertyType == typeof(Nullable<Int64>))
            {
                if (prop.GetValue(item) == null)
                    row[prop.Name] = 0;
                else
                    row[prop.Name] = prop.GetValue(item);
            }
            else
                row[prop.Name] = prop.GetValue(item);                    

        }
        currentDT.Rows.Add(row);
    }

    return currentDT;
}

public static DataTable CreateTable<T>()
{
    Type entType = typeof(T);
    DataTable tbl = new DataTable(DTName);
    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entType);
    foreach (PropertyDescriptor prop in properties)
    {
        if (prop.PropertyType == typeof(Nullable<decimal>))
             tbl.Columns.Add(prop.Name, typeof(decimal));
        else if (prop.PropertyType == typeof(Nullable<int>))
            tbl.Columns.Add(prop.Name, typeof(int));
        else if (prop.PropertyType == typeof(Nullable<Int64>))
            tbl.Columns.Add(prop.Name, typeof(Int64));
        else
             tbl.Columns.Add(prop.Name, prop.PropertyType);
    }
    return tbl;
}
6
ответ дан 23 November 2019 в 03:10
поделиться

Я сам написал небольшую библиотеку для выполнения этой задачи. Он использует отражение только в первый раз, когда тип объекта должен быть преобразован в таблицу данных. Он излучает метод, который сделает всю работу по преобразованию типа объекта.

Это невероятно быстро. Вы можете найти это здесь: ModelShredder в GoogleCode

5
ответ дан 23 November 2019 в 03:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: