Frank R. Haugen Ответов: 2

Вероятность того, что значение имеет тот или иной тип (с#)


Я создаю программу для создания класса со свойствами на основе набора данных (ничего особенного, просто инструмент для упрощения жизни).

Прямо сейчас я тестирую CSV-данные звезд, так как в нем много колонок, и это несколько грязные данные.

То, что я делаю прямо сейчас, заключается в том, что я беру набор данных, извлекаю заголовки, а затем создаю класс (удалено около 30 строк для краткости):
class 
{
	public int Id { get; set; }
	public string Hip { get; set; }
	public string Hd { get; set; }
	public string Hr { get; set; }
	public decimal Ci { get; set; }
	public decimal X { get; set; }
	public decimal Y { get; set; }
	public decimal Z { get; set; }
}

Это делается путем циклического перебора первой строки данных, оценивая ячейки с помощью этого метода.:
public static string Evaluate(string input)
{
    string output = "string";
    
    if (decimal.TryParse(input, out var result)) { output = "decimal"; }
    if (DateTime.TryParse(input, out var result1)) { output = "DateTime"; }
    if (int.TryParse(input, out var result2)) { output = "int"; }

    if (input == "") { output = "string"; }

    return output;
}

Это немного неуклюже, но это не конкурс красоты

Что мне нужно, так это оценить первые 5 строк данных, а затем сравнить, какой тип данных является наиболее вероятным. Оказывается, просто выборка первой строки-плохая идея, поэтому я ищу, какой тип является правильным для трех из пяти строк (если ни один тип не имеет этого, то это строка).

Данные:
id	hip	hd	ra	dec	dist	pmra	pmdec
0			0	0	0	0	0
1	1	224700	0.00006	1.089009	219.7802	-5.2	-1.88
2	2	224690	0.000283	-19.49884	47.9616	181.21	-0.93
3	3	224699	0.000335	38.859279	442.4779	5.24	-2.91
4	4	224707	0.000569	-51.893546	134.2282	62.85	0.16

Примечание: первый dataline-это Sol, ging it 0 as value in a column filled with decimals, поэтому просто проверять первую или одну строку было бы глупо, так как она не будет обрабатывать целое число, не показанное как 0.0.

Проект GitHub: https://github.com/frankhaugen/class-from-dataset

Что я уже пробовал:

Да, я погуглил, но мне либо не хватает слов, либо нет никакой информации по этому поводу

И я изучил возможность использования ML.NET для этой задачи, но она кажется несколько излишней, (но это может быть весело)

Eric Lynch

Как всегда, есть много способов получить одно и то же решение. Если вы ограничиваете себя общими типами данных C#, вы можете посмотреть на систему.Перечисление кодов типов. Это может быть лучше для представления возможных типов.

Одним из способов выполнения этой задачи может быть создание списка<Dictionary<TypeCode, int>>, где каждый элемент в списке представляет столбец данных. Затем каждая запись в словаре отслеживает, сколько раз встречается соответствующий тип данных (TypeCode).


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

Однако вам следует подумать, что делать в случае ничьей. Например, в большинстве случаев текст для TypeCode.Int32 (int) также допустим для TypeCode.Десятичное число (в десятичной системе).

Опять же, только одна возможность. Есть много других подходов, которые также будут работать.

Richard MacCutchan

Глядя на ваш образец, каждое число выглядит как допустимое десятичное число. Возможно, вам следует переупорядочить свои тесты, чтобы наиболее вероятный тип был проверен последним

Frank R. Haugen

Да, обнаружил, что после этого был разнесен, так как десятичное значение может представлять собой дату и время. Но это тривиально

Richard MacCutchan

Ну, проблема в том, что десятичное число может представлять собой дату-время, но нет никакой гарантии, что это именно то, что оно представляет. Без контекста такая программа, скорее всего, будет в значительной степени догадкой.

Frank R. Haugen

Догадки будут в порядке, так как это должно быть рукой помощи, а не идеальным решением :-)

2 Ответов

Рейтинг:
10

Frank R. Haugen

Я посмотрел на комментарии, и они направили меня по правильному пути.

Я перешел на DataTable из словарей и списков (он уже настроен для 2-мерных данных). Мой код нуждается в большой чистке и комментировании, но теперь он делает то, что я хочу, (в основном)

Мой код для создания datatable:

static void GenerateDataTable()
{
    dt.TableName = "Stars";
    string[] heads = inputData[0].Replace(" ", "").Split(',');

    foreach (string head in heads)
    {
        dt.Columns.Add(new DataColumn() { ColumnName = head });
    }

    for (int i = 1; i < inputData.Count; i++)
    {
        dt.Rows.Add(inputData[i].Replace(" ", "").Split(','));
    }

    Dictionary<int, string> testDict = new Dictionary<int, string>();

    for (int i = 0; i < dt.Columns.Count; i++)
    {
        List<string> testList = new List<string>();
        for (int j = 0; j < 500; j++)
        {
            testList.Add(EvaluateVariableType.Evaluate(dt.Rows[j].ItemArray[i].ToString()));
            
        }
        
        testDict.Add(i, MostOccurences(testList));
    }

    for (int i = 0; i < testDict.Count; i++)
    {
        HeadersAndTypes.Add(heads[i], testDict[i]);

        Console.WriteLine(testDict[i]);
    }
}

Для подсчета происшествий я сделал вот что (украдено из stackexchange):
static string MostOccurences(List<string> input)
{
    string output;

    try
    {
        var groupsWithCounts = from s in input
                               group s by s into g
                               select new
                               {
                                   Item = g.Key,
                                   Count = g.Count()
                               };

        var groupsSorted = groupsWithCounts.OrderByDescending(g => g.Count);
        string mostFrequest = groupsSorted.First().Item;

        output = mostFrequest;
    }
    catch (Exception e)
    {
        output = e.Message;
    }

    return output;
}


Рейтинг:
1

#realJSOP

Попробуйте эту статью: CSV/Excel File Parser - A Revisit[^]

Он создает строго типизированный DataTable либо путем определения самих типов, либо с помощью типов, заданных программистом.