#c# #datatable
#c# #datatable
Вопрос:
Я довольно новичок в мире C #, и мне нужна помощь в поиске решения. Я пишу программу, которая содержит таблицу данных, отформатированную следующим образом:
Возврат | 100 | 200 | 300 | 400 |
---|---|---|---|---|
A | 1 | 2 | 3 | 4 |
B | 2 | 3 | 4 | 5 |
C | 3 | 4 | 5 | 6 |
D | 4 | 5 | 6 | 7 |
У меня есть пользовательский ввод, в каком столбце они хотят выполнить поиск, скажем, «300», и они также вводят число. Предполагая, что поиск выполняется сверху вниз, если это число меньше первого значения, оно должно возвращать значение первого столбца той же строки.
Итак, давайте продолжим с «300» в качестве столбца поиска. Если пользователь вводит 4.7, я хочу, чтобы мне вернули «C», поскольку 4.7 меньше или равно 5. Значения в 100-400 столбцах всегда будут в порядке от наименьшего к наибольшему. Я знаю, что это должно быть возможно, но последние несколько часов, пытаясь выяснить, как логически сравнивать значения, мне трудно, и любая помощь или направление приветствуются.
Я должен отметить, что я использую эту таблицу данных в другой функции, чтобы в значительной степени делать обратное, поэтому я бы не хотел реструктурировать эту таблицу данных, поскольку я уже потратил время на ее создание.
Редактировать — Я думаю, что у меня это получилось (кажется, работает), но я отправляю свое решение для проверки. Может быть, это не лучший способ сделать это?
var returnValue = string.Empty;
foreach (DataColumn col in Table503().Columns)
{
if (col.ColumnName == searchColumn)
{
for (var i = 0; i < Table503().Rows.Count; i )
{
foreach (DataRow row in Table503().Rows)
{
if (searchValue <= Convert.ToDouble(row[searchColumn]))
{
returnValue = Convert.ToString(row["Return"]);
break;
}
}
}
}
}
return returnValue;
Комментарии:
1. Пожалуйста, опубликуйте код, который вы пробовали до сих пор при попытке
2. Я изменил свой исходный пост, чтобы включить рабочее решение (пока)
3. Пожалуйста, скажите мне
Table503()
, не генерирует ли новая таблица каждый раз, когда она вызывается…4. @Charlieface Вы правы, в данном случае так и было, но я исправил это в своем реальном коде. Хороший улов — это то, что я полностью замалчивал. Спасибо!
5. Вы нашли какой-либо правильный ответ?, пожалуйста, отметьте его
Ответ №1:
Вы можете использовать LINQ, я написал консольный проект с вашим примером, в этом я использую LINQ и математические Floor, Ceiling и round, которые вы можете использовать в своей бизнес-логике:
using System;
using System.Data;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable("MyDataTable");
dt.Columns.Add("Return");
dt.Columns.Add("100");
dt.Columns.Add("200");
dt.Columns.Add("300");
dt.Columns.Add("400");
dt.Rows.Add("Un", 1, 2, 3, 4);
dt.Rows.Add("B", 2, 3, 4, 5);
dt.Rows.Add("C", 3, 4, 5, 6);
dt.Rows.Add("D", 4, 5, 6, 7);
Again:
Console.WriteLine($"Write Column[100, 200, 300, 400]:");
var SearchColumn = Console.ReadLine();
Console.WriteLine($"Write value:");
double val;
bool isDouble = double.TryParse(Console.ReadLine(), out val);
if (!isDouble) goto notShow;
string returned;
// Return First 5 for 4.7, Return "C"
returned = dt.Select().FirstOrDefault(o => int.Parse(o[SearchColumn].ToString()) == Math.Floor(val))[0].ToString();
Console.WriteLine($"Math.Floor: {returned}");
// Return First 4 for 4.7, Return "B"
returned = dt.Select().FirstOrDefault(o => int.Parse(o[SearchColumn].ToString()) == Math.Ceiling(val))[0].ToString(); ;
Console.WriteLine($"Math.Ceiling: {returned}");
// Return First 5 for 4.7, Return "C"
returned = dt.Select().FirstOrDefault(o => int.Parse(o[SearchColumn].ToString()) == Math.Round(val))[0].ToString(); ;
Console.WriteLine($"Math.Round: {returned}nn");
goto Again;
notShow:
Console.WriteLine("Error: not is valid");
goto Again;
}
}
эти строки выполняют поиск в коллекции строк и возвращают значение первого столбца:
returned = dt.Select().FirstOrDefault(o => int.Parse(o[SearchColumn].ToString()) == Math.Floor(val))[0].ToString();
returned = dt.Select().FirstOrDefault(o => int.Parse(o[SearchColumn].ToString()) == Math.Ceiling(val))[0].ToString(); ;
returned = dt.Select().FirstOrDefault(o => int.Parse(o[SearchColumn].ToString()) == Math.Round(val))[0].ToString(); ;
Ответ №2:
С помощью LINQ я получил все строки, которые больше или равны входному значению, и выбрал первую. Значения столбцов уже приведены в порядке возрастания в соответствии с вопросом.
// Create a sample DataTable
DataTable dt = new DataTable("tbl");
DataColumn dtColumn;
dtColumn = new DataColumn();
dtColumn.DataType = typeof(string);
dtColumn.ColumnName = "Return";
dtColumn.ReadOnly = false;
dtColumn.Unique = true;
dt.Columns.Add(dtColumn);
dtColumn = new DataColumn();
dtColumn.DataType = typeof(Int32);
dtColumn.ColumnName = "100";
dtColumn.ReadOnly = false;
dtColumn.Unique = true;
dt.Columns.Add(dtColumn);
dtColumn = new DataColumn();
dtColumn.DataType = typeof(Int32);
dtColumn.ColumnName = "200";
dtColumn.ReadOnly = false;
dtColumn.Unique = true;
dt.Columns.Add(dtColumn);
dtColumn = new DataColumn();
dtColumn.DataType = typeof(Int32);
dtColumn.ColumnName = "300";
dtColumn.ReadOnly = false;
dtColumn.Unique = true;
dt.Columns.Add(dtColumn);
DataRow dr = dt.NewRow();
dt.Rows.Add(dr);
dr["Return"] = "A";
dr["100"] = 1;
dr["200"] = 2;
dr["300"] = 3;
dr = dt.NewRow();
dt.Rows.Add(dr);
dr["Return"] = "B";
dr["100"] = 2;
dr["200"] = 3;
dr["300"] = 4;
dr = dt.NewRow();
dt.Rows.Add(dr);
dr["Return"] = "C";
dr["100"] = 3;
dr["200"] = 4;
dr["300"] = 5;
dr = dt.NewRow();
dt.Rows.Add(dr);
dr["Return"] = "D";
dr["100"] = 4;
dr["200"] = 5;
dr["300"] = 6;
double inputVal = 4.7;
// The Column data is already ordered , as mentioned in the question
var t1 = dt.AsEnumerable().Where(r1 => r1.Field<int>("300") >= inputVal) // all records greater than the input value
.Select(a => a[0]).ToList() // select value from first column
.FirstOrDefault(); // the closest one