简体   繁体   English

使用LINQ根据字段获取列表中的下一项

[英]Grab next item in a list based on a field with LINQ

I have a list of employee's, and I'd like to select the next person in the list based on their status. 我有一个员工列表,我想根据他们的状态在列表中选择下一个人。 I don't have my source code on hand, but basically my list is formed like this. 我手头没有源代码,但是基本上我的列表是这样形成的。

public class Employee
{
    public string Name { get; set; }
    public string Status{ get; set; }

        public Employee( string name, string status )
        {
            this.Status = status;
            this.Name = name;
        }
}

I add items like so. 我添加这样的项目。

        List<Employee> r = new List<Employee>();
        r.Add( new Employee( string Name, string status );

What I need is a way to search through the list at a starting name, say "Bob Smith", and get the next person in the list that has a status of "yes". 我需要的是一种以名字开头(例如“鲍勃·史密斯”)搜索列表,并让列表中下一个状态为“是”的人的方法。 However if it's at the end of the list, I'd start back at the beginning and go until I got to "Bob Smith" again. 但是,如果它在列表的末尾,我会从头开始,然后一直走到再次到达“鲍勃·史密斯”。

I tried a clump of for loops, but it was cumbersome and awkward, and worst of all, didn't work. 我尝试了一堆for循环,但是它笨拙而笨拙,最糟糕的是,它没有用。

This would all be in a function that returns a dictionary list, so I can use it with another function. 这全部都在返回字典列表的函数中,因此我可以将其与另一个函数一起使用。 In psuedo-code I'd like it to work kinda like this, so I can iterate through the dictionary of names in a for loop, using an int to grab items from it. 在伪代码中,我希望它可以像这样工作,因此我可以在in循环中遍历名称字典,并使用int从中获取内容。

    public Dictionary<int,string> listToMail( int employeeNeeded )
    {
        Dictionary<int, string> tmpList = new Dictionary<int, string>();

        string lastEmployee = getLastEmployee();

        for( int x = 0; x < employeeNeeded; x++ )
        {
            /* find the next in the list that has a "yes" status. 
               If at the end of the list, start back at the beginning until we 
               reach the start by. If nothing found, exit out.*/

            tmpList.Add( x, EmployeeName );
        }

        if ( tmpList.Count > 0 )
        {
            return tmpList;

        } else {

            return null;
        }

    }
var person = 
   r.SkipWhile(e => e.Name != "Bob Smith") // skip people until Bob Smith
    .Skip(1) // go to next person
    .SkipWhile(e => e.Status != "yes") // skip until status equal 'yes'
    .FirstOrDefault(); // get first person, if any

if (person == null)
    person = r.TakeWhile(e => e.Name != "Bob Smith")
              .FirstOrDefault(e => e.Status != "yes");

I used lazyberezosky approach, but included all cases, its not very elegant but it works ;): 我使用了lazyberezosky方法,但包括了所有情况,它不是很优雅,但是可以起作用;):

        List<Employee> list = new List<Employee>();
        list.Add(new Employee("Walter White", "yes"));
        list.Add(new Employee("Bob Smith", "no"));
        list.Add(new Employee("Walter Junior", "no"));

        //get first employee after Bob with status "yes"
        Employee result = list.SkipWhile(e => e.Name != "Bob Smith") // skip people until Bob Smith
                         .Skip(1) // go to next person
                         .SkipWhile(e => e.Status != "yes") // skip until status equal 'yes'
                         .FirstOrDefault(); // get first person, if any

        if (result == null)
        {
            //get the first employee in list with status "yes"
            result = list.SkipWhile(e => e.Status != "yes") // skip until status equal 'yes'
                         .FirstOrDefault(); // get first person, if any

            if (result == null)
            {
                //get Bob Smith if no employee has status "yes"
                result = list.SkipWhile(e => e.Name != "Bob Smith")
                        .FirstOrDefault();                               
            }
        }

A simpler approach would be: 一个更简单的方法是:

        Employee res = list.SkipWhile(e => e.Name != "Bob Smith") // skip people until Bob Smith
                         .Skip(1) // go to next person
                         .SkipWhile(e => e.Status != "yes")
                         .Union(list.SkipWhile(e => e.Status != "yes"))
                         .FirstOrDefault();

if no employee has status "yes", res is null! 如果没有员工的状态为“是”,则res为空! so pay attention to not access the value of res without checking if its null... 因此请注意不要在不检查res是否为null的情况下访问res的值。

and thanks again to lazyberezosky for the starting point ;) 并再次感谢lazyberezosky的起点;)

Think this should work 认为这应该工作

public static Dictionary<int,string> listToMail(string startAtName, int needed)
    {
        var firstPart = r.SkipWhile(e => e.Name != startAtName);
        var secondPart = r.TakeWhile(e => e.Name != startAtName);

        var results = firstPart.Union(secondPart)
            .Where(e => e.Status == "yes")
            .Take(needed)
            .Select((e, i) => new { Key = i, Name = e.Name })
            .ToDictionary(kv => kv.Key, kv => kv.Name);
        if (results.Any())
            return results;
        else
            return null;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM