Jasl
Jasl

Reputation: 1395

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)            
{  
    // access listAddr.Address.Length  
    // print longest address  
    // print shortest address  
}  

Upvotes: 1

Views: 294

Answers (4)

digEmAll
digEmAll

Reputation: 57210

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 ...

Upvotes: 4

Serkan Hekimoglu
Serkan Hekimoglu

Reputation: 4284

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

Upvotes: 0

Bablo
Bablo

Reputation: 916

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

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500675

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;
        }
    }
}

Upvotes: 2

Related Questions