开发者

Question about length of an object in LINQ

I have a List. I want to print the longest address.

Pseudocode

foreach (var i in listAddr)      开发者_如何学Go      
{  
    // access listAddr.Address.Length  
    // print longest address  
    // print shortest address  
}  


Very roughly, with no foreach:

var sortedAddr = listAddr.OrderBy(x => x.Address.Length);

var longestAddr = sortedAddr.Last();
var shortedAddr = sortedAddr.First();

As Jon said, this has O(n log n) complexity. But could be reasonable if you don't have extreme performance need.

EDIT:

If you have a lot of same-length addresses you can do this:

var sortedGroups = listAddr.GroupBy(x => x.Address.Length).OrderBy(x => x.Key);
var longestAddresses = sortedGroups.Last();
var shortestAddresses = sortedGroups.First();

// just print iterating over longestAddresses and shortestAddresses ...


It sounds like you want MaxBy and MinBy functionality, e.g.

var maxEntry = listAddr.MaxBy(entry => entry.Address.Length);
Console.WriteLine(maxEntry.Address);
var minEntry = listAddr.MinBy(entry => entry.Address.Length);
Console.WriteLine(minEntry.Address);

Unfortunately there's nothing like this in plain LINQ to Objects, but we have an implementation in MoreLINQ and I believe Reactive Extensions has one in System.Interactive too.

Obviously you can sort by address size descending and then take the first result... that will be O(n log n) instead of O(n) complexity... that may well be fine in most cases. It feels inelegant to me though :)

Code from the MoreLINQ implementation of MaxBy (without comments :)

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

    public static TSource MaxBy<TSource, TKey>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> selector, IComparer<TKey> comparer)
    {
        source.ThrowIfNull("source");
        selector.ThrowIfNull("selector");
        comparer.ThrowIfNull("comparer");
        using (IEnumerator<TSource> sourceIterator = source.GetEnumerator())
        {
            if (!sourceIterator.MoveNext())
            {
                throw new InvalidOperationException("Sequence was empty");
            }
            TSource max = sourceIterator.Current;
            TKey maxKey = selector(max);
            while (sourceIterator.MoveNext())
            {
                TSource candidate = sourceIterator.Current;
                TKey candidateProjected = selector(candidate);
                if (comparer.Compare(candidateProjected, maxKey) > 0)
                {
                    max = candidate;
                    maxKey = candidateProjected;
                }
            }
            return max;
        }
    }
}


This should work list.Max(x => x.Address) and list.Min(x => x.Address)


For ex, if you have a list like that

List<int> myList = new List<int>();

you are able to use myList.Max() and myList.Min() to get max and min values

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜