检查List C#中是否存在值

时间:2013-03-01 14:44:37

标签: c#

我有一个由存储过程填充的DataTable,以及包含Requests(RequestNumber and Tasks(TaskId)集合的数据表。当我通过任务到达第一个请求编号时,我将其添加到我的列表中,然后使用其他数据行,我检查列表以查看它们是否存在(if(dr["RequestNumber"].ToString() != acList[i].RequestNumber))如果有,我删除dataRow,如果不是我把它们添加到列表中。

这在顺序中很好用,但如果数据行和列表一个接一个,它就允许添加行。如果值存在于列表中,还有其他方法可以完成查找。

提前致谢。

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();
        }
      }
    }

4 个答案:

答案 0 :(得分:5)

使用LINQ,就像检查是否有匹配一样简单:

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

此外,似乎开头将dRow分配给dr的代码没有任何意义。只需在代码的其余部分直接使用dRow即可。而且我认为您不希望将(acList.Count == 0)视为一种特殊情况,因为这只会导致您必须复制逻辑,从而维护相同代码的两个单独副本。因此,如果我理解正确,这个简化的代码应该完成同样的事情:

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()
        });
    }
}

答案 1 :(得分:2)

这对于LINQ的 Union 方法来说非常棒,但它需要IEqualityComparer<AssignedClass>实现。除非你经常这样做,否则它可能不值得编码(即使它是10-ish线,如果正确完成)。不过,这会有所帮助:

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

,其中

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()
    }
}

比基于散列的解决方案稍微复杂一点,但很容易实现。

编辑:

如果您确实需要散列提供的额外性能,可以编写EqualityComparer(但请记住 these guidelines )。这样的解决方案最终看起来像这样:

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

答案 2 :(得分:0)

您可以使用HashSet<AssignedClass>,您只需要创建自定义IEqualityComarer<AssignedClass>,在其中检查传递对象的RequestNumber属性,并在{{1}的构造函数中传递此比较器的实例}}

修改

以下是HashSet

的可能实施方式
IEqualityComarer<AssignedClass>

<强> EDIT2: 或者你可以简单地使用HashSet来存储密钥,同时枚举行:

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();
    }
}

答案 3 :(得分:0)

使用linq选项并考虑到开始代码块和检查0条目似乎有点多余。我认为这个过程可以归结为

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()
    });
}