循环访问对象的自定义集合并删除重复项
本文关键字:删除 合并 集合 访问 对象 自定义 循环 | 更新日期: 2023-09-27 18:32:39
我有一个包含特定自定义对象的自定义集合类。对象类称为 TestReport
,保存这些对象的集合类称为 TestReports
它继承System.Collections.CollectionBase
。 TestReport
包含属性 LocalReportID
和 ScoreTypeID
。我想做的是遍历对象的集合并删除任何重复项,这在我的例子中意味着对象之间的ScoreTypeID
和LocalReportID
是相同的。到目前为止,我所拥有的遗漏了对象并且没有正确完成工作,我对解决方案感到非常困惑。请注意,每次存在重复项时,我都会获取该对象并将其放置在另一个集合中,然后再删除重复项。我并没有打算这样做,这只是我的想法,但如果有更好的方法来实现它,请告诉我:
TestReports objTestReportsContainer = new TestReports();
foreach (TestReport objTestReport in objTestReports)
{
objTestReportsContainer.Add(objTestReport);
}
objTestReports.Clear();
for (int i = 0; i < objTestReportsContainer.Count - 1; i++)
{
for (int k = objTestReportsContainer.Count - 1; k > 0; k--)
{
if ((objTestReportsContainer.Item(k).LocalReportID == objTestReportsContainer.Item(i).LocalReportID) &&
(objTestReportsContainer.Item(k).ScoreTypeID == objTestReportsContainer.Item(i).ScoreTypeID) &&
(objTestReportsContainer.Item(k).LocalReportID != 0))
{
objTestReports.Add(objTestReportsContainer.Item(k));
objTestReportsContainer.Remove(objTestReportsContainer.Item(i));
objTestReportsContainer.Remove(objTestReportsContainer.Item(k));
}
else if ((objTestReportsContainer.Item(k).ScoreTypeID == objTestReportsContainer.Item(i).ScoreTypeID) &&
(objTestReportsContainer.Item(k).LocalReportID == 0) &&
(objTestReportsContainer.Item(i).LocalReportID == 0))
{
objTestReports.Add(objTestReportsContainer.Item(k));
objTestReportsContainer.Remove(objTestReportsContainer.Item(i));
objTestReportsContainer.Remove(objTestReportsContainer.Item(k));
}
}
}
原始项目填充在 objTestReports
中,我将它们移到objTestReportsContainer
,以便我可以对该集合进行所有工作,并将最终筛选的集合添加回 objTestReports
。这段代码似乎每次都会遗漏一些项目,我找不到解决方案。有什么更好的方法来解决这个问题吗?
编辑 我忘了注意,在 if 语句中,我将 LocalReportID 是否为 0 分开,因为如果它是 TestReport 对象,则被视为平均报告,如果它不是 0,则它是带报告。只是为了澄清,但对于迭代流应该如何工作可能并不重要。
编辑 2 按照要求,这里是我对TestReports
的定义。模式UIGetLocalTestReports
就是我所说的用TestReport
obejcts填充集合。
public class TestReports : System.Collections.CollectionBase
{
public TestReports()
{
//constructor?
List.Clear();
}
public void Add(TestReport objTestReport)
{
// add a testReport to the testReports collection
List.Add(objTestReport);
}
public void Remove(int index)
{
// remove a testReport from the testReports collection
if (index <= Count - 1 && index >= 0)
{
List.RemoveAt(index);
}
}
public void Remove(TestReport objTestReport)
{
//remove a TestReport from the collection without passing an index
List.Remove(objTestReport);
}
public TestReport Item(int Index)
{
//get the item requested and explicitly cast to the testSubject type
return (TestReport)List[Index];
}
public void UIGetLocalTestReports(SqlConnection mySqlConn, int intTestTypeID)
{
//clear list
List.Clear();
if (mySqlConn.State == ConnectionState.Open)
{
SqlCommand myComm = new SqlCommand("StatsGen_UI_ByTest_GetReports", mySqlConn);
myComm.CommandType = CommandType.StoredProcedure;
myComm.Parameters.Add(new SqlParameter("@intTestTypeID", intTestTypeID));
try
{
SqlDataReader dr = myComm.ExecuteReader();
if (dr.HasRows)
{
TestReport objTestReport;
while (dr.Read())
{
objTestReport = new TestReport();
objTestReport.TestReportID = dr.GetInt32(0);
objTestReport.TestReportName = dr.GetString(1);
objTestReport.SummaryDataSP = dr.GetString(2);
objTestReport.ScoreTypeID = dr.GetInt32(3);
if (dr.GetValue(4) != DBNull.Value)
objTestReport.LocalReportID = dr.GetInt32(4);
else
objTestReport.LocalReportID = 0;
List.Add(objTestReport);
}
}
dr.Close();
}
catch (SqlException)
{
//TODO: Add some error handling here.
}
}
}
}
让我知道这段代码是否让你更接近:
var keepers =
objTestReports
.Cast<TestReport>()
.GroupBy(x => new { x.LocalReportID, x.ScoreTypeID })
.SelectMany(x => x.Take(1))
.ToArray();
objTestReports.Clear();
foreach (var objTestReport in keepers)
{
objTestReports.Add(objTestReport);
}
您可以调用objTestReports.OfType<TestReport>()
来获取IEnumerable<TestReport>
并使用 LINQ 继续工作。
可以使用非重复扩展方法来获取不同项。
IEnumerable<TestReport> reportsAsEnumerable = objTestReports.OfType<TestReport>().Distinct();
如果TestReport没有实现IEquatable,你应该实现它,或者使用自定义的IEqualityComparer(参见 http://msdn.microsoft.com/en-us/library/bb338049(v=vs.110(.aspx(