首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算实体的时间窗口

计算实体的时间窗口
EN

Code Review用户
提问于 2019-06-11 10:06:54
回答 3查看 361关注 0票数 6

我已经做了一些代码,在多个实体上操作,并为它们创建“时间窗口”。基本上,实体将包含状态,通常以布尔或int的形式。它们将被时间戳,为了减少在大日期范围内创建图表时的行数,我正在计算5分钟、15分钟和60分钟的时间窗口。如果我正在计算5分钟的时间窗口,并且状态从00:00:00到00:02:59为真,从00:03:00开始为false,则一天的前5分钟的时间窗口为真,因为状态为3/5分钟。

我使用了自定义属性、泛型和反射,以检查实体具有哪些属性以及需要处理哪些属性。

代码可以工作,但我相信它可以改进。

有时,代码对16个实体中的数千行快速工作,即对CalculateTimeWindows<T>()方法的16个调用(不到1秒),但有时非常慢(大约需要45秒)。有什么办法优化这段代码吗?

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

namespace Services.Helpers
{
    #region Custom Attributes
    [AttributeUsage(AttributeTargets.Property)]
    public class DoNotCopyIntoTimeWindow : System.Attribute { } // leave default

    [AttributeUsage(AttributeTargets.Property)]
    public class IsProcessedIntoTimeWindow : System.Attribute { } // calculate time window for this property

    [AttributeUsage(AttributeTargets.Property)]
    public class IsTimeWindowDate : Attribute { } // attribute to mark property as the datetime

    [AttributeUsage(AttributeTargets.Property)]
    public class IsTimeWindowIdentifier : Attribute { } // this is the time window property
    #endregion

    public class TimeWindow
    {
        #region Structs
        public struct TimeWindowDictionary
        {
            public string Name { get; set; }
            public Dictionary<NullObject<dynamic>, int> Dictionary { get; set; }
        }

        public struct NullObject<T>
        {
            [DefaultValue(true)]
            private readonly bool isnull;// default property initializers are not supported for structs

            private NullObject(T item, bool isnull) : this()
            {
                this.isnull = isnull;
                Item = item;
            }

            public NullObject(T item) : this(item, item == null)
            {
            }

            public static NullObject<T> Null()
            {
                return new NullObject<T>();
            }

            public T Item { get; private set; }

            public bool IsNull()
            {
                return isnull;
            }

            public static implicit operator T(NullObject<T> nullObject)
            {
                return nullObject.Item;
            }

            public static implicit operator NullObject<T>(T item)
            {
                return new NullObject<T>(item);
            }

            public override string ToString()
            {
                return (Item != null) ? Item.ToString() : "NULL";
            }

            public override bool Equals(object obj)
            {
                if (obj == null)
                    return IsNull();

                if (!(obj is NullObject<T>))
                    return false;

                var no = (NullObject<T>)obj;

                if (IsNull())
                    return no.IsNull();

                if (no.IsNull())
                    return false;

                return Item.Equals(no.Item);
            }

            public override int GetHashCode()
            {
                if (IsNull())
                    return 0;

                var result = Item.GetHashCode();

                if (result >= 0)
                    result++;

                return result;
            }
        }
        #endregion

        public static IEnumerable<T> CalculateTimeWindows<T>(DateTime dateFrom, DateTime dateTo, List<T> stateModels) where T : new()
        {
            if (stateModels.Count() == 0)
                return new List<T>();

            dateFrom = GetPropertiesAndDictionaries(dateFrom, stateModels, out PropertyInfo datePropertyInfo, out List<PropertyInfo> copyProperties, out PropertyInfo timeWindowIdentifier, out int size, out TimeWindowDictionary[] dictionaries, out int i);

            return CalculateTimeWindow(dateFrom, dateTo, stateModels, 5, datePropertyInfo, copyProperties, timeWindowIdentifier, size, dictionaries, i)
                        .Concat(CalculateTimeWindow(dateFrom, dateTo, stateModels, 15, datePropertyInfo, copyProperties, timeWindowIdentifier, size, dictionaries, i))
                        .Concat(CalculateTimeWindow(dateFrom, dateTo, stateModels, 60, datePropertyInfo, copyProperties, timeWindowIdentifier, size, dictionaries, i));
        }

        public static IEnumerable<T> CalculateTimeWindow<T>(DateTime dateFrom, DateTime dateTo, List<T> stateModels, byte timeWindowMinutes, PropertyInfo datePropertyInfo, List<PropertyInfo> copyProperties, PropertyInfo timeWindowIdentifier, int size, TimeWindowDictionary[] dictionaries, int i) where T : new()
        {
            if (stateModels.Count() > 0)
            {
                DateTime currentWindowFrom, currentWindowTo, nextWindowFrom;
                nextWindowFrom = dateFrom;
                int itemPointer = 0;
                T prevItem = default;
                T prevTimeWindow = default;

                KeyValuePair<NullObject<dynamic>, int> maxValue = new KeyValuePair<NullObject<dynamic>, int>();
                int j = 1;

                do // one time window
                {
                    for (i = 0; i < size; i++)
                        dictionaries[i].Dictionary = new Dictionary<NullObject<dynamic>, int>();

                    currentWindowFrom = nextWindowFrom;
                    nextWindowFrom = currentWindowFrom.AddMinutes(timeWindowMinutes);
                    currentWindowTo = nextWindowFrom.AddSeconds(-1);

                    var calculateTime = currentWindowFrom;

                    for (itemPointer = itemPointer; itemPointer < stateModels.Count(); itemPointer++)
                    {
                        var item = stateModels.ElementAt(itemPointer);

                        var date = (DateTime)datePropertyInfo.GetValue(item);

                        if (date >= currentWindowTo)
                            break;

                        var endDate = (date > currentWindowTo) ? nextWindowFrom : date; // state might extend more than the end of the time window
                        CalculateStateSeconds(prevItem, dictionaries, calculateTime, endDate);

                        prevItem = item;
                        calculateTime = (date < currentWindowFrom) ? currentWindowFrom : date; // to fix the 'yesterday' date
                    }

                    if (calculateTime < currentWindowTo)
                        CalculateStateSeconds(prevItem, dictionaries, calculateTime, nextWindowFrom);

                    if (dictionaries[0].Dictionary.Count > 0)
                    {
                        bool sameAsPrevious = (prevTimeWindow != null);
                        var output = new T();

                        foreach (var dictionary in dictionaries)
                        {
                            //var valToSet = dictionary.Dictionary.FirstOrDefault(x => x.Value.Equals(dictionary.Dictionary.Values.Max())).Key.Item;

                            for (i = 0; i < dictionary.Dictionary.Count; i++)
                            {
                                maxValue = dictionary.Dictionary.First();
                                for (j = 1; j < dictionary.Dictionary.Count; j++)
                                {
                                    var valuePair = dictionary.Dictionary.ElementAt(j);

                                    if (valuePair.Value > maxValue.Value)
                                        maxValue = valuePair;
                                }
                            }
                            var valToSet = maxValue.Key.Item;

                            if (sameAsPrevious)
                            {
                                var prevVal = GetValue(prevTimeWindow, dictionary.Name);

                                if (valToSet == null && prevVal == null)
                                { }
                                else if ((valToSet == null && prevVal != null) || (valToSet != null && prevVal == null) || !valToSet.Equals(prevVal))
                                    sameAsPrevious = false;
                            }

                            SetValue(output, dictionary.Name, valToSet);
                        }

                        if (!sameAsPrevious)
                        {
                            foreach (var copyProperty in copyProperties)
                                SetValue(output, copyProperty.Name, copyProperty.GetValue(prevItem));

                            timeWindowIdentifier.SetValue(output, timeWindowMinutes);

                            datePropertyInfo.SetValue(output, currentWindowFrom);

                            prevTimeWindow = output;

                            yield return output;
                        }
                    }
                }
                while (nextWindowFrom <= dateTo);
            }
        }

        private static DateTime GetPropertiesAndDictionaries<T>(DateTime dateFrom, List<T> stateModels, out PropertyInfo datePropertyInfo, out List<PropertyInfo> copyProperties, out PropertyInfo timeWindowIdentifier, out int size, out TimeWindowDictionary[] dictionaries, out int i) where T : new()
        {
            Type tType = typeof(T);
            var propInfos = tType.GetProperties();

            datePropertyInfo = propInfos.Single(p => p.GetCustomAttributes(typeof(IsTimeWindowDate), true).Any());
            var firstDate = (DateTime)datePropertyInfo.GetValue(stateModels.First());

            if (firstDate < dateFrom)
                dateFrom = new DateTime(firstDate.Year, firstDate.Month, firstDate.Day, firstDate.Hour, 0, 0, DateTimeKind.Utc);

            var properties = propInfos.Where(p => p.GetCustomAttributes(typeof(IsProcessedIntoTimeWindow), true).Any()).Select(x => x.Name);
            copyProperties = propInfos.Where(p => !p.GetCustomAttributes(typeof(IsTimeWindowIdentifier), true).Any() && !p.GetCustomAttributes(typeof(DoNotCopyIntoTimeWindow), true).Any() && !p.GetCustomAttributes(typeof(IsTimeWindowDate), true).Any() && !p.GetCustomAttributes(typeof(IsProcessedIntoTimeWindow), true).Any() && p.CanWrite && !p.GetMethod.IsVirtual).ToList();
            timeWindowIdentifier = propInfos.Single(p => p.GetCustomAttributes(typeof(IsTimeWindowIdentifier), true).Any());

            size = properties.Count();
            dictionaries = new TimeWindowDictionary[size];

            i = 0;
            foreach (var property in properties)
            {
                dictionaries[i] = new TimeWindowDictionary() { Name = property };
                i++;
            }

            return dateFrom;
        }

        private static dynamic GetValue(object inputObject, string propertyName)
        {
            Type type = inputObject.GetType();
            PropertyInfo propertyInfo = type.GetProperty(propertyName);
            return propertyInfo.GetValue(inputObject);
        }

        private static void SetValue(object inputObject, string propertyName, object propertyVal)
        {
            //find out the type
            Type type = inputObject.GetType();

            //get the property information based on the type
            PropertyInfo propertyInfo = type.GetProperty(propertyName);

            if (propertyVal != null)
            {
                //find the property type
                Type propertyType = propertyInfo.PropertyType;

                //Convert.ChangeType does not handle conversion to nullable types
                //if the property type is nullable, we need to get the underlying type of the property
                var targetType = IsNullableType(propertyType) ? Nullable.GetUnderlyingType(propertyType) : propertyType;

                //Returns an System.Object with the specified System.Type and whose value is
                //equivalent to the specified object.
                propertyVal = Convert.ChangeType(propertyVal, targetType);
            }

            //Set the value of the property
            propertyInfo.SetValue(inputObject, propertyVal, null);

        }

        private static bool IsNullableType(Type type)
        {
            return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
        }

        private static void CalculateStateSeconds<T>(T prevItem, IEnumerable<TimeWindowDictionary> dictionaries, DateTime calculateTime, DateTime endDate)
        {
            if (prevItem != null)
            {
                var seconds = Convert.ToInt32(endDate.Subtract(calculateTime).TotalSeconds);

                Type tType = typeof(T);

                foreach (var dictionary in dictionaries)
                {
                    PropertyInfo propertyInfo = tType.GetProperty(dictionary.Name);
                    var key = propertyInfo.GetValue(prevItem);

                    dictionary.Dictionary.TryGetValue(key, out int existingSeconds);
                    dictionary.Dictionary[key] = existingSeconds + seconds;
                }
            }
        }
    }
}

下面是一个示例类和单元测试:

代码语言:javascript
复制
public abstract class MyBaseModel : ICloneable
{
    [DoNotCopyIntoTimeWindow]
    public int Id { get; set; }

    public short fk_TenantId { get; set; }

    [IsTimeWindowIdentifier]
    public byte TimeWindow { get; set; }

    [IsTimeWindowDate]
    public DateTime Date { get; set; }

    [IsProcessedIntoTimeWindow]
    public byte ActuallyAnEnum { get; set; }

    public abstract bool CalculatorOn { get; }

    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

public class MyModel : MyBaseModel
{
    public short ShortId { get; set; }
    public short AnotherShortId { get; set; }

    [IsProcessedIntoTimeWindow]
    public decimal Value { get; set; }

    public override bool CalculatorOn
    {
        get
        {
            throw new NotImplementedException();
        }
    }
}

[TestMethod]
public void TestLowerResolution()
{
    /* generate test data */
    DateTime dateFrom = new DateTime(2018, 1, 28, 15, 0, 0, DateTimeKind.Utc);
    var dateTo = dateFrom.AddDays(1).AddSeconds(-1);

    var myValues = new List<MyModel>();

    myValues.Add(new MyModel()
    {
        Date = new DateTime(2018, 1, 9, 15, 48, 46, DateTimeKind.Utc),
        ShortId = 5,
        AnotherShortId = 0,
        TimeWindow = 0,
        Value = 30,
        fk_TenantId = 1006
    });

    myValues.Add(new MyModel()
    {
        Date = new DateTime(2018, 1, 29, 10, 11, 31, DateTimeKind.Utc),
        ShortId = 5,
        AnotherShortId = 0,
        TimeWindow = 0,
        Value = 14336,
        fk_TenantId = 1006
    });

    myValues.Add(new MyModel()
    {
        Date = new DateTime(2018, 1, 29, 10, 11, 59, DateTimeKind.Utc),
        ShortId = 5,
        AnotherShortId = 0,
        TimeWindow = 0,
        Value = 30,
        fk_TenantId = 1006
    });

    var windows = TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myValues).ToList();
}

编辑:空列表的性能问题上更新的代码

EN

回答 3

Code Review用户

回答已采纳

发布于 2019-06-14 12:12:12

var firstDate = (DateTime)datePropertyInfo.GetValue(stateModels.First()); if (firstDate < dateFrom) dateFrom = new DateTime(firstDate.Year, firstDate.Month, firstDate.Day, firstDate.Hour, 0, 0, DateTimeKind.Utc);

您接受了第一个stateModel,但是如果没有按日期订购呢?

for (itemPointer = itemPointer;itemPointer < stateModels.Count();itemPointer++)

itemPointer = itemPointer不是死胡同:

代码语言:javascript
复制
for (; itemPointer < stateModels.Count(); itemPointer++)

CalculateTimeWindow<T>(..., ..., int i)的最后一个参数是用来自GetPropertiesAndDictionaries()out int i参数初始化的,但是实际上没有使用这些值,而且第一次使用i作为迭代器索引设置为0,那么为什么要将它作为参数而不仅仅是局部变量呢?如果它不被使用的话,把它处理掉。

这是:

代码语言:javascript
复制
    public static IEnumerable<T> CalculateTimeWindows<T>(DateTime dateFrom, DateTime dateTo, List<T> stateModels) where T : new()
    {
        if (stateModels.Count() == 0)
            return new List<T>();

        dateFrom = GetPropertiesAndDictionaries(dateFrom, stateModels, out PropertyInfo datePropertyInfo, out List<PropertyInfo> copyProperties, out PropertyInfo timeWindowIdentifier, out int size, out TimeWindowDictionary[] dictionaries, out int i);

        return CalculateTimeWindow(dateFrom, dateTo, stateModels, 5, datePropertyInfo, copyProperties, timeWindowIdentifier, size, dictionaries, i)
                    .Concat(CalculateTimeWindow(dateFrom, dateTo, stateModels, 15, datePropertyInfo, copyProperties, timeWindowIdentifier, size, dictionaries, i))
                    .Concat(CalculateTimeWindow(dateFrom, dateTo, stateModels, 60, datePropertyInfo, copyProperties, timeWindowIdentifier, size, dictionaries, i));
    }

我会写成:

代码语言:javascript
复制
  public static IEnumerable<T> CalculateTimeWindows<T>(DateTime dateFrom, DateTime dateTo, List<T> stateModels) where T : new()
  {
    if (stateModels == null || stateModels.Count() == 0)
      yield break; // return new List<T>();

    dateFrom = GetPropertiesAndDictionaries(
      dateFrom, 
      stateModels, 
      out PropertyInfo datePropertyInfo, 
      out List<PropertyInfo> copyProperties, 
      out PropertyInfo timeWindowIdentifier, 
      out int size, 
      out TimeWindowDictionary[] dictionaries, 
      out int i);

    byte[] windowDurations = { 5, 15, 60 };

    foreach (byte duration in windowDurations)
    {
      foreach (T result in CalculateTimeWindow(dateFrom, dateTo, stateModels, duration, datePropertyInfo, copyProperties, timeWindowIdentifier, size, dictionaries, i))
      {
        yield return result;
      }
    }

或作为:

代码语言:javascript
复制
  public static IEnumerable<T> CalculateTimeWindows<T>(DateTime dateFrom, DateTime dateTo, List<T> stateModels) where T : new()
  {
    if (stateModels.Count() == 0)
      return new List<T>();

    dateFrom = GetPropertiesAndDictionaries(
      dateFrom,
      stateModels,
      out PropertyInfo datePropertyInfo,
      out List<PropertyInfo> copyProperties,
      out PropertyInfo timeWindowIdentifier,
      out int size,
      out TimeWindowDictionary[] dictionaries,
      out int i);

    byte[] windowDurations = { 5, 15, 60 };

    return windowDurations.SelectMany(wd =>
      CalculateTimeWindow(
        dateFrom,
        dateTo,
        stateModels,
        wd,
        datePropertyInfo,
        copyProperties,
        timeWindowIdentifier,
        size,
        dictionaries,
        i));
   }

如果您想要添加一个新的时间窗口,它更易读和易于维护。

代码语言:javascript
复制
    copyProperties = propInfos
      .Where(
        p => 
          !p.GetCustomAttributes(typeof(IsTimeWindowIdentifier), true).Any() 
          && !p.GetCustomAttributes(typeof(DoNotCopyIntoTimeWindow), true).Any() 
          && !p.GetCustomAttributes(typeof(IsTimeWindowDate), true).Any() 
          && !p.GetCustomAttributes(typeof(IsProcessedIntoTimeWindow), true).Any() 
          && p.CanWrite 
          && !p.GetMethod.IsVirtual).ToList();

在上面,您可以通过检查数据不是什么属性来确定从哪些属性中获取负面数据。我想,我应该定义一个ValuePropertyAttribute来标记要从其中获取数据的属性。维护起来更容易,因为您将始终能够从该属性中看出哪些属性值是从对象上复制的。

在处理属性(设置和获取)时,PropertyInfos和strings (名称)之间的转换有点过大。

您可以通过更改以下内容的定义来减少这种情况:

代码语言:javascript
复制
  public struct TimeWindowDictionary
  {
    public string Name { get; set; }
    public Dictionary<NullObject<dynamic>, int> Dictionary { get; set; }
  }

代码语言:javascript
复制
  public struct TimeWindowDictionary
  {
    public PropertyInfo PropertyInfo { get; set; }
    public Dictionary<NullObject<dynamic>, int> Dictionary { get; set; }
  }

然后改变一切以适应这一点--例如:

代码语言:javascript
复制
    var properties = propInfos.Where(p => p.GetCustomAttributes(typeof(IsProcessedIntoTimeWindow), true).Any()).Select(x => x.Name);
    size = properties.Count();

    dictionaries = new TimeWindowDictionary[size];
    i = 0;

    foreach (var property in properties)
    {
      dictionaries[i] = new TimeWindowDictionary() { Name = property };
      i++;
    }

可以是:

代码语言:javascript
复制
    dictionaries =
      propInfos
      .Where(p => p.GetCustomAttributes(typeof(IsProcessedIntoTimeWindow), true).Any())
      .Select(p => new TimeWindowDictionary { PropertyInfo = p })
      .ToArray();

    size = dictionaries.Length;

GetValue(...)可以是:

代码语言:javascript
复制
  private static dynamic GetValue(object inputObject, PropertyInfo propertyInfo)
  {
    return propertyInfo.GetValue(inputObject);
    //Type type = inputObject.GetType();
    //System.Reflection.PropertyInfo propertyInfo = type.GetProperty(propertyName);
    //return propertyInfo.GetValue(inputObject);
  }

SetValue(...)也可以具有以下签名:

代码语言:javascript
复制
  private static void SetValue(object inputObject, PropertyInfo propertyInfo, object propertyVal)

CalculateStateSeconds<T>(...)中:

代码语言:javascript
复制
        //PropertyInfo propertyInfo = tType.GetProperty(dictionary.Name);
        var key = dictionary.PropertyInfo.GetValue(prevItem);
        dictionary.Dictionary.TryGetValue(key, out int existingSeconds);
        dictionary.Dictionary[key] = existingSeconds + seconds;
代码语言:javascript
复制
  private static DateTime GetPropertiesAndDictionaries<T>(
    DateTime dateFrom,
    List<T> stateModels,
    out PropertyInfo datePropertyInfo,
    out List<PropertyInfo> copyProperties,
    out PropertyInfo timeWindowIdentifier,
    out int size,
    out TimeWindowDictionary[] dictionaries,
    out int i) where T : new()
  {

当所有这些参数从一个方法传递到另一个方法时,我想我会为它们创建一个容器对象,并将其传递给它们。或者,您可以使用这些参数作为成员来使类状态化,这样您就可以完全避免使用方法的参数。当然,这些方法应该是非静态成员。您唯一的静态方法可能是这样的:

代码语言:javascript
复制
  public static IEnumerable<T> GetTimeWindows<T>(DateTime dateFrom, DateTime dateTo, List<T> stateModels) where T : new()
  {
    TimeWindow timeWindow = new TimeWindow(dateFrom, dateTo, stateModels);
    return timeWindow.Calculate();
  }

其中,TimeWindow类应该有一个适当的泛型类型参数。

票数 4
EN

Code Review用户

发布于 2019-06-15 18:23:45

替代方法

我不使用属性和反射,而是选择一组使用类型特定日期和值选择器方法作为参数的泛型方法。

首先,返回按时间段分组的项的方法:

代码语言:javascript
复制
public static IEnumerable<TimeSegmentItems<T>> GetItemsPerTimeSegment(
    IEnumerable<T> items,
    DateTime from,
    DateTime to,
    TimeSpan segmentDuration,
    Func<T, DateTime> getTimestamp) { ... }

// Contains all items within a given time segment,
// as well as the last item from the preceding time segment
// (that item determines the initial state):
public class TimeSegmentItems<T>
{
    public DateTime Start { get; }
    public DateTime End { get; }
    public IEnumerable<T> Items { get; }
}

然后,获取给定时间段的主导值的实用方法:

代码语言:javascript
复制
public static TValue GetDominantValue<TItem, TValue>(
    IEnumerable<TItem> items,
    DateTime from,
    DateTime to,
    Func<TItem, DateTime> getTimestamp,
    Func<TItem, TValue> getValue) { ... }

它们结合在一起,可以让你做以下事情:

代码语言:javascript
复制
GetItemsPerTimeSegment(myValues, fromDate, toDate, TimeSpan.FromMinutes(5), m => m.Date)
    .Select(segment => new MyModel {
        Value = GetDominantValue(segment.Items, segment.Start, segment.End, m => m.Date, m => m.Value),
        ActuallyAnEnum = GetDominantValue(segment.Items, segment.Start, segment.End, m => m.Date, m => m.ActuallyAnEnum),
    });

这是可以进一步简化的,但这是它的主旨。

比较

将其与最初的方法进行比较:

  • 反射和dynamic都比较慢,特别是在使用dynamic时会丢失编译时检查。这种方法应该更简洁、更健壮和(更快)。
  • 对于属性,您只限于可以添加属性的类型。这种方法允许您处理任何类型,甚至可以为同一类型创建不同的“视图”,而代价是必须编写特定于类型的逻辑(日期和值选择器,以及最终的结果生成代码)。
  • 这些实用程序方法不只是一个完成所有事情的公共方法,而是专注于一个特定的任务,这使得它们更加可重用。您可以将主导值逻辑替换为平均值逻辑,而不必触摸时间段分组逻辑。您还可以在此基础上构建一个基于属性/反射的层,如果有必要,可以消除对特定类型代码的需求。
票数 5
EN

Code Review用户

发布于 2019-06-13 20:41:18

我发现了一些我觉得很奇怪的东西

for (i = 0; i < dictionary.Dictionary.Count; i++) { maxValue = dictionary.Dictionary.First(); for (j = 1; j < dictionary.Dictionary.Count; j++) { var valuePair = dictionary.Dictionary.ElementAt(j); if (valuePair.Value > maxValue.Value) maxValue = valuePair; } } var valToSet = maxValue.Key.Item;

这个看起来可以用

代码语言:javascript
复制
var valToSet = dictionary.Values.Max();

如果您正在尝试获取带有最大值的键,则可以使用以下内容

代码语言:javascript
复制
var valToSet = dictionary.OrderByDescending(x => x.Value).First().Key;

https://stackoverflow.com/a/42508315/1214743上找到的,一定要对相同的值进行测试。

我还发现了一些我也会做不同的事情

if ( sameAsPrevious ) { var prevVal = GetValue(prevTimeWindow,dictionary.Name);if (valToSet == null & prevVal == null) {} else ((valToSet == null & prevVal != null != null& prevVal == null!valToSet!=null&prevVal== null) x!valToSet.Equals(PrevVal)=== false;}

您的if/else语句可以这样编写:

代码语言:javascript
复制
if (valToSet == null && prevVal == null)
{ 
}
else
{
    sameAsPrevious = (valToSet == preval);
}

因为

  • 如果valToSet是空的,而另一个值是不一样的,那么它的工作方式也会相反。这将使sameAsPrevious == false
  • 如果它们都为null,则会在初始值if语句中捕获它们。
  • 如果它们都有一个值,并且是相同的,那么无论如何我们都希望sameAsPrevious值是true。如果valToSet == prevalsameAsPrevious设置为true,则应该是在这种情况下。
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/222072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档