简体   繁体   English

检查List C#中是否存在值

[英]Check if value exist in a List C#

I have a DataTable that is filled by a Stored Procedure, and from that datatable which contains a collection of Requests(RequestNumber and Tasks(TaskId) . When I have reach the first Request number with a Task, I add it to my list, then with additional datarows, I check the list to see if they exist( if(dr["RequestNumber"].ToString() != acList[i].RequestNumber) ) if they do, I delete the dataRow, if not I add them to the list. 我有一个由存储过程填充的DataTable,以及包含Requests(RequestNumber and Tasks(TaskId)集合Requests(RequestNumber and Tasks(TaskId) 。当我通过任务到达第一个请求号时,我将它添加到我的列表中,然后使用额外的数据行,我检查列表以查看它们是否存在( if(dr["RequestNumber"].ToString() != acList[i].RequestNumber) )如果有,我删除dataRow,如果没有我添加它们到列表。

This works good in sequential order, but if the datarow and list are off by one it allows the row to be added. 这在顺序中很好用,但是如果数据行和列表偏离一个,则允许添加行。 Is there any other way to accomplish finding if the value exists in the list. 如果值存在于列表中,还有其他方法可以完成查找。

Thanks in advance. 提前致谢。

foreach (DataRow dRow in dt.Rows)
{
    DataRow dr = dt.NewRow();
    dr["Project"] = dRow["Project"];
    dr["RequestNumber"] = dRow["RequestNumber"];
    dr["RequestId"] = dRow["RequestId"];
    dr["TaskType"] = dRow["TaskType"];
    dr["TaskId"] = dRow["TaskId"];
    dr["TaskStatus"] = dRow["TaskStatus"];
    dr["AssignedTo"] = dRow["AssignedTo"];
    dr["DateDue"] = dRow["DateDue"];


    if (acList.Count == 0)
    {
        acList.Add(new AssignedClass
        {
            Project = dr["Project"].ToString(),
            RequestNumber = dr["RequestNumber"].ToString(),
            RequestId = dr["RequestId"].ToString(),
            TaskType = dr["TaskType"].ToString(),
            TaskId = dr["TaskId"].ToString(),
            TaskStatus = dr["TaskStatus"].ToString(),
            AssignedTo = dr["AssignedTo"].ToString(),
            DateDue = dr["DateDue"].ToString()
        });
    }

    else
    {
        for (int i = 0; i < acList.Count; i++)
        {

        if(dr["RequestNumber"].ToString() != acList[i].RequestNumber)
        {
            acList.Add(new AssignedClass
            {
                Project = dr["Project"].ToString(),
                RequestNumber = dr["RequestNumber"].ToString(),
                RequestId = dr["RequestId"].ToString(),
                TaskType = dr["TaskType"].ToString(),
                TaskId = dr["TaskId"].ToString(),
                TaskStatus = dr["TaskStatus"].ToString(),
                AssignedTo = dr["AssignedTo"].ToString(),
                DateDue = dr["DateDue"].ToString()
            });
        }
        else
        {
            dr.Delete();
        }
      }
    }

Using LINQ, it's as simple as checking if there are any matches: 使用LINQ,就像检查是否有匹配一样简单:

if ( !acList.Any(a => a.RequestNumber == dr["RequestNumber"].ToString() )
    acList.Add( ... );

Also, it seems that the code at the beginning assigning dRow to dr has no purpose. 此外,似乎开头将dRow分配给dr的代码没有任何意义。 Just use dRow directly throughout the rest of your code. 只需在代码的其余部分直接使用dRow即可。 And I don't think you want to treat (acList.Count == 0) as a special case, because that just causes you to have to duplicate your logic and thus maintain two separate copies of the same code. 而且我认为你不想将(acList.Count == 0)视为特殊情况,因为这只会导致你必须复制你的逻辑,从而维护相同代码的两个独立副本。 So if I understood everything correctly, this simplified code should accomplish the same thing: 所以,如果我理解正确,这个简化的代码应该完成同样的事情:

foreach (DataRow dRow in dt.Rows)
{
    if ( !acList.Any(a => a.RequestNumber == dRow["RequestNumber"].ToString() )
    {
        acList.Add(new AssignedClass
        {
            Project = dRow["Project"].ToString(),
            RequestNumber = dRow["RequestNumber"].ToString(),
            RequestId = dRow["RequestId"].ToString(),
            TaskType = dRow["TaskType"].ToString(),
            TaskId = dRow["TaskId"].ToString(),
            TaskStatus = dRow["TaskStatus"].ToString(),
            AssignedTo = dRow["AssignedTo"].ToString(),
            DateDue = dRow["DateDue"].ToString()
        });
    }
}

This would be a great job for LINQ's Union method, but it requires an IEqualityComparer<AssignedClass> implementation. 这对于LINQ的Union方法来说是一个很好的工作,但它需要一个IEqualityComparer<AssignedClass>实现。 Unless you do this often, it's probably not worth coding (even though it's 10-ish lines if done properly). 除非你经常这样做,否则它可能不值得编码(即使它是10-ish线,如果正确完成)。 This would help, however: 但这会有所帮助:

acList = acList
    .Concat(from row in dt.Rows
            from ac in acList
            where ac.RequestNumber != row["RequestNumber"].ToString()
            select AssignedClassFromDataRow(row))
    .ToList();

where 哪里

private static AssignedClass AssignedClassFromDataRow(DataRow row)
{
    // maybe some checks...
    return new AssignedClass
    {
        Project = dRow["Project"].ToString(),
        RequestNumber = dRow["RequestNumber"].ToString(),
        RequestId = dRow["RequestId"].ToString(),
        TaskType = dRow["TaskType"].ToString(),
        TaskId = dRow["TaskId"].ToString(),
        TaskStatus = dRow["TaskStatus"].ToString(),
        AssignedTo = dRow["AssignedTo"].ToString(),
        DateDue = dRow["DateDue"].ToString()
    }
}

Slightly more time complex than a hash-based solution, but simple enough to implement. 比基于散列的解决方案稍微复杂一点,但足够简单实现。

EDIT: 编辑:

If you actually need the extra performance provided by hashing, you can write the EqualityComparer (but keep in mind these guidelines ). 如果您确实需要散列提供的额外性能,则可以编写EqualityComparer(但请记住这些准则 )。 Such solution would look like this in the end: 这样的解决方案最终看起来像这样:

acList = acList
    .Union(
        dt.Rows.Select(AssignedClassFromDataRow),
        new MyAssignedClassRequestNumberComparer())
    .ToList();

You can use HashSet<AssignedClass> , all you need is to create custom IEqualityComarer<AssignedClass> in which you check RequestNumber property of passed objects, and pass instance of this comparer in constructor of HashSet 您可以使用HashSet<AssignedClass> ,您只需要创建自定义IEqualityComarer<AssignedClass>在其中检查传递对象的RequestNumber属性,并在HashSet构造函数中传递此RequestNumber的实例

Edit 编辑

Here is possible implementation of IEqualityComarer<AssignedClass> : 以下是IEqualityComarer<AssignedClass>可能实现:

public class AssignedClassComparer : IEqualityComparer<AssignedClass>
{
    public bool Equals(AssignedClass x, AssignedClass y)
    {
        return x.RequestNumber == y.RequestNumber;
    }

    public int GetHashCode(AssignedClass obj)
    {
        return obj.RequestNumber.GetHashCode();
    }
}

EDIT2: Or you can simply use HashSet to store only keys, while enumerating through rows: EDIT2:或者你可以简单地使用HashSet来存储密钥,同时枚举行:

var keys = new HashSet<string>();

foreach (DataRow dRow in dt.Rows)
{
    if (keys.Add(dRow["RequestNumber"].ToString()))
    {
        acList.Add(new AssignedClass
        {
            Project = dRow["Project"].ToString(),
            RequestNumber = dRow["RequestNumber"].ToString(),
            RequestId = dRow["RequestId"].ToString(),
            TaskType = dRow["TaskType"].ToString(),
            TaskId = dRow["TaskId"].ToString(),
            TaskStatus = dRow["TaskStatus"].ToString(),
            AssignedTo = dRow["AssignedTo"].ToString(),
            DateDue = dRow["DateDue"].ToString()
        });
    }
}

With the option of linq and taking into account that the beginning code block and the check for 0 entries seem a bit redundant. 使用linq选项并考虑到开始代码块和检查0条目似乎有点多余。 I think the process could boil down to 我认为这个过程可以归结为

var distinctRows = dt.Rows.GroupBy(x => x["RequestNumber"]).Select(x => x.First());
acList.AddRange(distinctRows.Select(x => x.MapToAssignedClass());


// Added Mapping method for readability
public static AssignedClass MapToAssignedClass(this DataRow dr)
{
    return new AssignedClass
    {
        Project = dr["Project"].ToString(),
        RequestNumber = dr["RequestNumber"].ToString(),
        RequestId = dr["RequestId"].ToString(),
        TaskType = dr["TaskType"].ToString(),
        TaskId = dr["TaskId"].ToString(),
        TaskStatus = dr["TaskStatus"].ToString(),
        AssignedTo = dr["AssignedTo"].ToString(),
        DateDue = dr["DateDue"].ToString()
    });
}

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

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