Как сортировать записи во время выполнения на основе временного интервала?

#c# #.net

#c# #.net

Вопрос:

У меня есть приведенный ниже код, который отлично работает для меня. Для демонстрационных целей я добавляю в список только несколько записей в режиме реального времени, этот список постоянно пополняется новыми значениями в секунду. вопрос в том, как сортировать эти данные в реальном времени на основе временного интервала? Размещенный ниже код в постоянно работающем webjob.

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

    public DateTime GetStartOfPeriodByMins(int numMinutes) 
    {
        int oldMinutes = Time.Minute;
        int newMinutes = (oldMinutes / numMinutes) * numMinutes;

        DateTime startOfPeriod = new DateTime(Time.Year, Time.Month, Time.Day, Time.Hour, newMinutes, 0);

        return startOfPeriod;
    }
}


List<MyObject> inputList = new List<MyObject>();

inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 0), Value = 12});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 2), Value = 11});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 5), Value = 13});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 15), Value = 14});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 45), Value = 12});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 55), Value = 11});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 16, 0), Value = 13});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 16, 1), Value = 16});


var resultSet = inputList
    .GroupBy(i => i.GetStartOfPeriodByMins(1))
    .Select(gr =>
        new 
        {
            StartOfPeriod = gr.Key,
            Min = gr.Min(item => item.Value),
            Max = gr.Max(item => item.Value),
            Open = gr.OrderBy(item => item.Time).First().Value,
            Close = gr.OrderBy(item => item.Time).Last().Value
        });

var my = resultSet.ToList();
  

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

введите описание изображения здесь

Я хочу обрабатывать данные inputList так, чтобы через каждые 1 минуту я получал последний набор данных за последние 1 минуту, чтобы я мог использовать его для дальнейших вычислений.

Комментарии:

1. кто пометил его закрытым, не указав никаких входных данных: ( попробуйте дать какой-нибудь фрагмент кода, который я могу попробовать. Эти типы вопросов очень сложны и полезны для многих пользователей.

2. Я бы предположил, что кто-то пометил это для закрытия, поскольку неясно, о чем вы здесь спрашиваете. Что именно означает, что «InputList будет получать непрерывные новые данные из API»?

3. О, хорошо, я разместил этот код в azure webjob, поэтому api — это websocket api, который постоянно выдает мне данные о тике, которые я добавляю в inputlist… Пожалуйста, укажите, как это отсортировать

Ответ №1:

Поскольку он продолжает вставки (add), вы можете использовать SortedSet вместо этого в списке.

 public class MyObjectComparer : IComparer<MyObject>
{
    public int Compare(MyObject x, MyObject y)
    {
        return x.Time.CompareTo(y.Time);
    }
}

var inputList = new SortedSet<MyObject>(new MyObjectComparer());

inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 0), Value = 12});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 2), Value = 11});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 5), Value = 13});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 15), Value = 14});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 45), Value = 12});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 15, 55), Value = 11});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 16, 0), Value = 13});
Thread.Sleep(1000);
inputList.Add(new MyObject() {Time = new DateTime(2020, 10, 10, 9, 16, 1), Value = 16});

  

Таким образом, для каждого добавления набор (список) будет в правильном порядке.

 public class MyObject 
{
    public double Value { get; set; }
    public DateTime Time { get; set; }
    
    public DateTime Created { get; } = DateTime.Now;
    public DateTime Ttl { get; } = DateTime.Now.AddMinues(5);
    public DateTime? Persisted { get; set; }

    public bool IsDead => DateTime.Now > Ttl;
    public bool IsPersisted => Persisted.HasValue;
    public bool TimeToPersist => IsPersisted == false amp;amp; DateTime.Now > Create.AddMinutes(2);

    public DateTime GetStartOfPeriodByMins(int numMinutes) 
    {
        int oldMinutes = Time.Minute;
        int newMinutes = (oldMinutes / numMinutes) * numMinutes;

        DateTime startOfPeriod = new DateTime(Time.Year, Time.Month, Time.Day, Time.Hour, newMinutes, 0);

        return startOfPeriod;
    }
}
  

Комментарии:

1. Большое спасибо… есть ли какой-либо способ сохранить данные только текущих 1 минут или 5 минут в новом списке, и через 1 или 5 минут он очистит старые данные?

2. нет, для этого у вас есть собственное состояние Persisted и TTL (время жизни).

3. Хорошо, я думаю, мне нужно создать новый список, в котором я могу сохранять последние данные за 1 минуту или 5 минут из Inputlist. Правильно? Любой пример фрагмента кода, который вы можете придумать, я также попробую с моей стороны, например, использовать MemoryCache спасибо

4. Я обновил ответ некоторыми свойствами MyObject , которые должны поддерживать ваш запрос. Просто укажите минуты….

5. Вы должны запустить список «вручную» и удалить их, то IsDead == true же самое касается тех, которые должны быть сохранены.