4

I cannot solve a problem for several hours now. Here is a simplified scenario. Let's say there is a list of people with their bids. I'm trying to find a person with the highest bid and return the name. I am able to find the highest bid, but how to I output the name?

        List<String[]> list = new List<String[]>();
        String[] Bob = { "Alice", "19.15" };
        String[] Alice = {"Bob", "28.20"};
        String[] Michael = { "Michael", "25.12" };

        list.Add(Bob);
        list.Add(Alice);
        list.Add(Michael);

        String result = list.Max(s => Double.Parse(s.ElementAt(1))).ToString();

        System.Console.WriteLine(result);

As a result I get 28.20, which is correct, but I need to display "Bob" instead. There were so many combinations with list.Select(), but no success. Anyone please?

Alex
  • 937
  • 3
  • 20
  • 44
  • 2
    Instead of using a Dictionary, it might be wiser to use a class for this. Check out Michel Keijzers' answer – Manuzor Aug 15 '12 at 13:39

5 Answers5

9

The best solution from an architectural point of view is to create a separate class (e.g. Person) that contains two properties Name and Bid of each person and a class Persons that contains the list of persons.

Then you can easily use a LINQ command.

Also instead of storing bids as string, think if bids as floating point or decimal values would be better (or store it in cents and use an int).

I don't have a compiler by hand so it's a bit out of my head:

public class Person
{
    public string Name { get; set; }
    public float  Bid  { get; set; }

    public Person(string name, float bid)
    {
        Debug.AssertTrue(bid > 0.0);
        Name = name;
        Bid = bid;
    }
}

public class Persons : List<Person>
{
    public void Fill()
    {
        Add(new Person("Bob", 19.15));
        Add(new Person("Alice" , 28.20));
        Add(new Person("Michael", 25.12));
    }
}

In your class:

var persons = new Persons();
persons.Fill();

var nameOfHighestBidder = persons.MaxBy(item => item.Bid).Name;
Console.WriteLine(nameOfHighestBidder);
Michel Keijzers
  • 15,025
  • 28
  • 93
  • 119
  • 1
    I do agree, the class would be easier to deal with. But due to the nature of the problem (web services, etc) I didn't want to create additional class. Thank you for your time! – Alex Aug 15 '12 at 13:49
  • 1
    Doesn't the Max method you used there return an int? – Şafak Gür Aug 15 '12 at 13:51
  • No problem at all ... I extended the answer anyway to show others how classes can help increase readability and splitting responsibilities. – Michel Keijzers Aug 15 '12 at 13:52
  • I changed Max to MaxBy, assuming it returns the person with the maximum bid, and than take the name of that person. – Michel Keijzers Aug 15 '12 at 13:54
  • Is it [MoreLinq](https://github.com/morelinq/MoreLINQ)? I don't recall a `MaxBy` in .NET Framework. – Şafak Gür Mar 16 '19 at 21:12
  • @ŞafakGür Yes ... see https://stackoverflow.com/questions/3188693/how-can-i-get-linq-to-return-the-object-which-has-the-max-value-for-a-given-prop/3188751 – Michel Keijzers Mar 17 '19 at 00:07
5

You can use Jon Skeet's MaxBy.

For usage you can see this question e.g. in this case

list.MaxBy(s => Double.Parse(s.ElementAt(1)))[0]

More here

Community
  • 1
  • 1
Ankush
  • 2,454
  • 2
  • 21
  • 27
5

This works in the simple example. Not sure about the real one

var result = list.OrderByDescending(s => Double.Parse(s.ElementAt(1))).First();
Juan Ayala
  • 3,388
  • 2
  • 19
  • 24
3

Should work:

var max = list.Max(t => double.Parse(t[1]));
list.First(s => double.Parse(s[1]) == max)[0]; // If list is not empty
Şafak Gür
  • 7,045
  • 5
  • 59
  • 96
  • Thank you very much, this is the answer I was looking for! Maybe not as elegant, as defining a class, but I really tried to avoid it. Cheers! – Alex Aug 15 '12 at 13:47
2

After finding result just do as below:

list.First(x=>x[1] == result)[0]
Saeed Amiri
  • 22,252
  • 5
  • 45
  • 83