关于c#:如何返回另一个列表中三个最低值的列表

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

如何返回另一个列表中3个最低值的列表。例如,我想得到如下三个最低值:

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

为此:

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

可能是这样的函数:

1
out_list = function(in_list, 3)?

在"列表"和"输出列表"中声明如下:

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

你能帮我为这个开发一个C代码吗?可以给出进一步的解释。


您需要两个查询,一个用于确定最低的项目,另一个用于填充结果列表。您可以使用HashSet来加快抽搐速度:

1
2
3
4
5
6
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();

如果你真的只想要3个,而且有可能有重复,这是我想出来的最好的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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();


如果你真的想要那些奇怪的n,有一个简单的解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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();
}

对于您关于重复项的新要求,您可以限制返回的最大整数数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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();
}


可以使用Aggregate获取每个元素的Dictionary及其相应的允许出现次数,然后可以使用这些次数从输入列表中获取值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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;
}