То, что вы думаете, что вы хотите, это:
IEnumerable<object[]> allRowValues = dataTable.AsEnumerable()
.SelectMany(dataRow =>
dataRow.Field<string>(1).Split(',').Select(drug => new[] { dataRow[0], drug, dataRow[2] }));
Но то, что вы действительно хотите, это:
IEnumerable<Record> allRowValues = dataTable.AsEnumerable()
.Select(dataRow => new Record(dataRow))
.SelectMany(record => record.SplitDrugs());
// ...
public class Record
{
public int Dosage { get; }
public string Drug { get; }
public string Patient { get; }
public Record(int dosage, string drug, string patient)
{
Dosage = dosage;
Drug = drug;
Patient = patient;
}
public Record(DataRow dataRow)
: this((int)dataRow["Dosage"], (string)dataRow["Drug"], (string)dataRow["Patient"])
{
}
public IEnumerable<Record> SplitDrugs()
{
return Drug.Split(',').Select(drug => new Record(Dosage, drug, Patient));
}
}
Краткое объяснение: с причудливым LINQ вы пытаетесь решить простослишком много мировых проблем извлекают информацию из таблицы данных, обрабатывают строки по очереди, применяют бизнес-логику и объединяют результат с новой таблицей данных.Это хороший способ написать подверженный ошибкам, нечитаемый, непроверяемый, нестабильный и не подлежащий обработке код.
Неполный список людей, которые в конечном итоге будут благодарны вам за выбор второго варианта:
- твое будущее
- твои товарищи по команде
- твой рецензент кода
- юнит-тестировщик
- конечный пользователь
- ваш учитель (если задание)
- ТАК сообщество
Пока я в нем, я сэкономлю вам время на отладку преобразования allRowValues
(которое в вашем случае имеетвведите IEnumerable<string[]>
) назад к DataTable
.Если вы думаете, что он будет содержать 3 столбца, то вы ошибаетесь.Вместо этого он будет содержать столбцы, такие как Length
, LongLength
, Rank
, ... Посмотрите на properties Массив класса , чтобы выяснить, почему.
Edit
OP уточнил исходное намерение в комментарии под другим ответом.
..., но я только что опубликовал прототип данных, в действительности там есть 180 столбцов. ДО мне нужно добавитьвсе 180 столбцов вручную в newRow.ItemArray, когда есть разделение значений, разделенных запятыми ??? Любой более простой способ?
Да, есть более простой способ.Привлекая обобщения, вы можете расширить использование за пределы этого ограниченного варианта использования:
// extension method
public static DataTable ExpandColumn<T>(this DataTable dataTable, string columnName,
Func<T, IEnumerable<T>> expandField)
{
var clonedDataTable = dataTable.Clone();
var columnIndex = dataTable.Columns.IndexOf(columnName);
var column = dataTable.Columns[columnIndex];
foreach (var dataRow in dataTable.AsEnumerable())
{
var valueToExpand = dataRow.Field<T>(column);
var expandedValues = expandField(valueToExpand);
var originalValues = dataRow.ItemArray;
foreach (var value in expandedValues)
{
originalValues[columnIndex] = value;
clonedDataTable.Rows.Add(originalValues);
}
}
return clonedDataTable;
}
// usage
var dataTableNew = dataTable.ExpandColumn<string>("Drug", drug => drug.Split(','));
Приведенный выше метод расширения клонирует DataTable
экземпляр, копируя исходные строки и расширяя значения в указанном столбце, применяя функцию expandField
для каждого значения.
Я бы хотел, чтобы вы извлекли урок из того, что я написал выше правки, и дважды подумайте о своем дизайне.