Как вернуть значение строки первого столбца на основе сравнения значений в другом столбце в C #?

#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