tags:

views:

61

answers:

4

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  
}  
+4  A: 

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 ...
digEmAll
I got it to work. One issue though..if there are more than 2 records with the longest address (same length), it prints only the last one. How can I resolve this?
Jasl
Check my edits ;)
digEmAll
+2  A: 

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;
        }
    }
}
Jon Skeet
Jon so I do not need a foreach? MaxBy will give longest. How to find shortest and print? Also I want to print the length of address as well as the address itself.
Jasl
Thanks for telling MinBy. Also can you suggest best way if I have to use vanilla LINQ only?
Jasl
@Jasl: There's no direct equivalent in LINQ. You could find the length of the shortest address and then find all addresses with that length, I suppose. (etc for longest)
Jon Skeet
A: 

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

Bablo
Nope, that will find the lexicographically first or last one. You could find the maximum or minimum address *length* of course...
Jon Skeet
A: 

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

Serkan Hekimoglu