user3664117
user3664117

Reputation: 49

How do I return a list of the three lowest values in another list

How do I return a list of the 3 lowest values in another list. For example, I want to get the 3 lowest values like this:

in_list = [2, 3, 4, 5, 6, 1]

To this:

out_list: [2, 3, n, n, n, 1]

Maybe a function like this:

out_list = function(in_list, 3)?

in_list and ouput list is declared like this:

List<string> in_list = new List<string>();
List<string> out_list = new List<string>();

Can you help me developing a C# code for this? Further explanation can be given.

Upvotes: 1

Views: 1533

Answers (3)

petelids
petelids

Reputation: 12815

You could use Aggregate to grab a Dictionary of each element with its corresponding number of allowed occurrences which you could then use to grab your values from the input list:

public static List<string> GetList(List<string> in_list, int max)
{
    Dictionary<string, int> occurrences = new Dictionary<string, int>();
    int itemsAdded = 0;

    in_list.OrderBy(x => x).Aggregate(occurrences, (list, aggr) =>
    {
        if (itemsAdded++ < max)
        {
            if (occurrences.ContainsKey(aggr))
                occurrences[aggr]++;
            else
                occurrences.Add(aggr, 1);
        }

        return list;
    });

    //occurrences now contains only each required elements 
    //with the number of occurrences allowed of that element

    List<string> out_list = in_list.Select(x =>
    {
        return (occurrences.ContainsKey(x) && occurrences[x]-- > 0 ? x : "n");
    }).ToList();

    return out_list;
}

Upvotes: 0

Tim Schmelter
Tim Schmelter

Reputation: 460098

You need two queries, one to determine the lowest items and one to fill the result-list. You can use a HashSet for faster loookups:

var lowest = new HashSet<String>(in_list
    .Select(s => new { s, val = int.Parse(s) })
    .OrderBy(x => x.val)
    .Take(3)
    .Select(x => x.s));
List<string> out_list = in_list.Select(s => lowest.Contains(s) ? s : "n").ToList();

If you actually only want 3 and duplicates are possible this is the best i've come up with:

var lowest = new HashSet<String>(in_list
    .Select(s => new { s, val = int.Parse(s) })
    .Distinct()
    .OrderBy(x => x.val)
    .Take(3)
    .Select(x => x.s));
List<string> out_list = in_list
    .Select((str, index) => new { str, index, value = int.Parse(str) })
    .GroupBy(x => x.str)
    .SelectMany(g => lowest.Contains(g.Key) 
        ?  g.Take(1).Concat(g.Skip(1).Select(x => new { str = "n", x.index, x.value }))
        :  g.Select(x => new { str = "n", x.index, x.value }))
    .OrderBy(x => x.index)
    .Select(x => x.str)
    .ToList();

Upvotes: 3

ken2k
ken2k

Reputation: 48975

If you really want those weird n, there's this simple solution:

public static List<string> Function(List<string> inputList, int max)
{
    var inputIntegers = inputList
        .Select(z => int.Parse(z))
        .ToList();

    var maxAuthorizedValue = inputIntegers
        .OrderBy(z => z)
        .Take(max)
        .Last();

    return inputIntegers
        .Select(z => z <= maxAuthorizedValue ? z.ToString() : "n")
        .ToList();
}

public static void Main(string[] args)
{
    List<string> in_list = new List<string> { "2", "3", "4", "6", "1", "7" };

    var res = Function(in_list, 3);

    Console.Read();
}

For your new requirement about duplicates, you could limit the max number of integer your return:

public static List<string> Function(List<string> inputList, int max)
{
    var inputIntegers = inputList.Select(z => int.Parse(z)).ToList();

    var maxAuthorizedValue = inputIntegers
        .OrderBy(z => z)
        .Take(max)
        .Last();

    // I don't really like that kind of LINQ query (which modifies some variable
    // inside the Select projection), so a good old for loop would probably
    // be more appropriated
    int returnedItems = 0;
    return inputIntegers.Select(z =>
        {
            return (z <= maxAuthorizedValue && ++returnedItems <= max) ? z.ToString() : "n";
        }).ToList();
}

Upvotes: 3

Related Questions