Поиск ближайших значений (сверху и снизу) для заданного значения - PullRequest
0 голосов
/ 03 октября 2019

У меня есть набор данных, который содержит Value и DateTime, и другой набор данных, который представляет временную шкалу. Временная шкала в этом случае состоит из округленных времен каждый с интервалом в 15 минут, но это может быть 30 или 60 минут ... Я хотел бы рассчитать линейную интерполяцию для определенных времен. Это время в другом наборе данных.

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

Вот моя реализация:

class Program
{
    static void Main(string[] args)
    {
        List<Items> items = Items.GetItems();
        List<DateTime> dt = GenerateTimeLine(items[0].Time, items[items.Count - 1].Time, 15);

        DateTime X1 = items[0].Time;
        double Y1 = items[0].Value;

        DateTime X2 = items[1].Time;
        double Y2 = items[1].Value;


        DateTime X = dt[0];
        double newValue = LinearInterpolation(X.ToOADate(), X1.ToOADate(), X2.ToOADate(), Y1, Y2);
    }      

Здесь выше я знаю время начала и время окончания, но я хотел бы иметь некоторый запрос, который будет каждый раз принимать набор данных TimeLine и проверять каждое время закрытия, принимать значения и интерполировать

    static double LinearInterpolation(double X, double X1, double X2, double Y1, double Y2)
    {
        if ((X2 - X1) == 0)
        {
            return (Y1 + Y2) / 2;
        }
        else
        {
            return Y1 + (X - X1) * (Y2 - Y1) / (X2 - X1);
        }

    }

    private static List<DateTime> GenerateTimeLine(DateTime start, DateTime end, int interval)
    {
        List<DateTime> lstD = new List<DateTime>();            

        int res = interval / 2;
        int mod = (interval / 2) % 2;
        int sec = 0;

        if (interval == 1)
            sec = 30;
        else if (interval == 0)
            sec = 0;

        var tempStart = start.AddMinutes(interval).AddSeconds(sec);
        var tempEnd = end.AddMinutes(interval).AddSeconds(sec);
        DateTime st = new DateTime(tempStart.Year, tempStart.Month, tempStart.Day, tempStart.Hour, (tempStart.Minute / interval) * interval, 0);
        DateTime en = new DateTime(tempEnd.Year, tempEnd.Month, tempEnd.Day, tempEnd.Hour, (tempEnd.Minute / interval) * interval, 0);

        lstD.Add(st);

        while (st <= en)
        {
            st = st.AddMinutes(interval);
            lstD.Add(st);
        }

        return lstD;
    }

}

public class Items
{

    public double Value { get; set; }
    public DateTime Time { get; set; }

    public static List<Items> GetItems()
    {

        string input =
            "| 31         | 2019-03-10 20:39:15 |\n" +
            "| 12         | 2019-03-10 20:44:16 |\n" +
            "| 12         | 2019-03-10 20:51:16 |\n" +
            "| 33         | 2019-03-10 21:08:44 |\n" +
            "| 33         | 2019-03-10 21:09:16 |\n" +
            "| 11         | 2019-03-10 21:24:17 |\n" +
            "| 9          | 2019-03-10 21:36:18 |\n" +
            "| 14         | 2019-03-10 21:50:18 |\n" +
            "| 15         | 2019-03-10 22:09:19 |\n" +
            "| 16         | 2019-03-10 22:24:19 |\n" +
            "| 31         | 2019-03-10 22:39:20 |\n" +
            "| 3          | 2019-03-10 22:54:20 |\n" +
            "| 34         | 2019-03-10 23:09:21 |\n" +
            "| 10         | 2019-03-10 23:24:20 |\n" +
            "| 17         | 2019-03-10 23:39:22 |\n" +
            "| 18         | 2019-03-10 23:54:23";

        List<Items> items = new List<Items>();

        string line = "";
        StringReader reader = new StringReader(input);
        while ((line = reader.ReadLine()) != null)
        {
            string[] lineArray = line.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

            Items newDate = new Items()
            {                   
                Value = int.Parse(lineArray[0]),
                Time = DateTime.Parse(lineArray[1])
            };

            items.Add(newDate);

        }

        return items;
    }

}

1 Ответ

0 голосов
/ 04 октября 2019

Я наконец-то понял, что вот код, если у кого-то возникнет похожая проблема

static void Main(string[] args)
{                
  List<Dates> dates = Dates.GetDates();
  List<DateTime> lstTimeLine = GenerateTimeLine(dates[0].Time, dates[dates.Count-1].Time, 10);

  List<Dates> lstInterpolated = new List<Dates>();
  foreach(var itm in lstTimeLine)
  {
       var target = itm;
       Console.WriteLine("############################ X = " + itm);
       var smaller = dates.Last(x => x.Time <= target);
       var bigger = dates.FirstOrDefault(x => x.Time >= target);
       if (bigger == null)
           bigger = smaller;

       Console.WriteLine(smaller.ID + " " + smaller.Time + " " + smaller.Value);
       Console.WriteLine(bigger.ID + " " + bigger.Time + " " + bigger.Value); }
}

Возможно, есть лучшее решение, но оно полностью удовлетворяет тому, что я хотел.

...