最接近的可能值

时间:2014-04-02 18:56:57

标签: c# .net linq

struct StreamInfo
{
    public Stream Stream {get; set;}
    public Quality Quality {get; set;}
}

public enum Quality
{
    VeryLow,
    Low,
    Medium,
    High,
    Maximum,
}
List<StreamInfo> streamInfos;

private Stream NearestLowerPossibleValue(Quality quality)
{
    ....
}

我有StreamInfoStream的结构PhotoQuality列表。我需要从集合中选择最接近的可能值的函数。这意味着,如果我在列表StreamInfo中有质量LowMediumMaximum。我打电话给NearestLowerPossibleValue(Quality.High)我需要获得中等质量的流,因为高丢失,如果有高我想要获得高质量的流。我正在寻找一些不错的解决方案,因为我没有发明任何好的解决方案。谢谢你的想法。

4 个答案:

答案 0 :(得分:1)

private static Stream NearestLowerPossibleValue(Quality preferedQuality)
{
    var streamInfoWithHigherQualityThanPreferred = streamInfos.Where(i => i.Quality <= preferedQuality);
    var mostSimilarToPreferred = streamInfoWithHigherQualityThanPreferred.MaxBy(i => i.Quality);
    return mostSimilarToPreferred.Stream;
}

如果streamInfos为null或为空,或者streamInfos不包含小于或等于preferedQuality的元素,则抛出异常。我使用nuget package MoreLing中的函数MaxBy,但是如果你不能添加这个包你可以使用:

public static class Extensions
{
    public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
    {
        return source.MaxBy<TSource, TKey>(selector, Comparer<TKey>.Default);
    }

    public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IComparer<TKey> comparer)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }
        if (selector == null)
        {
            throw new ArgumentNullException("selector");
        }
        if (comparer == null)
        {
            throw new ArgumentNullException("comparer");
        }
        using (IEnumerator<TSource> enumerator = source.GetEnumerator())
        {
            if (!enumerator.MoveNext())
            {
                throw new InvalidOperationException("Sequence contains no elements");
            }
            TSource current = enumerator.Current;
            TKey y = selector(current);
            while (enumerator.MoveNext())
            {
                TSource arg = enumerator.Current;
                TKey x = selector(arg);
                if (comparer.Compare(x, y) > 0)
                {
                    current = arg;
                    y = x;
                }
            }
            return current;
        }
    }
}

答案 1 :(得分:0)

public enum Quality
{
    VeryLow=1,
    Low=2,
    Medium=3,
    High=4,
    Maximum=5,
}

private PhotoQuality NearestLowerPossibleValue(PhotoQuality quality)
{
   int lenny = (int)quality;
   if (lenny != 1) lenny--;
   return (PhotoQuality)lenny;
}

答案 2 :(得分:0)

如果您可以修改StreamInfo结构,我建议您实施IComparable界面:

struct StreamInfo : IComparable<StreamInfo>
{
    public Stream Stream { get; set; }
    public PhotoQuality Quality { get; set; }

    public int CompareTo(StreamInfo other)
    {
        return Quality - other.Quality;
    }
}

public enum PhotoQuality
{
    VeryLow,
    Low,
    Medium,
    High,
    Maximum,
}
List<StreamInfo> streamInfos;

private Stream NearestLowerPossibleValue(PhotoQuality quality)
{
    return streamInfos.Where(si => si.Quality <= quality).Max().Stream;
}

如果没有,我们始终可以使用Aggregate方法:

private Stream NearestLowerPossibleValue(PhotoQuality quality)
{
    return streamInfos.Where(si => si.Quality <= quality)
        .Aggregate((si1, si2) => si1.Quality > si2.Quality ? si1 : si2).Stream;
}

答案 3 :(得分:-1)

利用枚举的整数值:

public enum Quality
{
    VeryLow,
    Low,
    Medium,
    High,
    Maximum,
}

IEnumerable<Quality> qualities = new List<Quality>
{
    Quality.Low,
    Quality.Medium,
    Quality.Maximum
};

Quality preferedQuality = Quality.High;

Quality actualQuality = qualities
    .TakeWhile(quality => quality <= preferedQuality) // arrow phun
    .Max(); // will throw if qualities is empty

Assert.AreEqual(Quality.Medium, actualQuality);