我有三个班级:
public class Error
{
public List<ErrorOccurrenceDetails> Occurrences { get; set; }
}
public class ErrorOccurrenceDetails
{
public Dictionary<DateTime, ErrorTime> Times { get; set; }
}
public class ErrorTime
{
public string Version { get; set; }
}
有一个 Error
有多个 Occurrences
发生在不同的 Times
中。每次都可以在不同的 Version
上发生。
我有一个 Error
列表。我需要删除没有提供版本的错误,例如如果用户只想看到版本“1.0”中的错误,其他版本(例如“1.1”、“1.2”)需要移除。但是,如果错误出现在版本“1.0”和其他版本上,过滤器应仅删除错误的出现,而不是整个错误。
我尝试这样做:
private IList<Error> errors;
private void Filter(string filterVersion)
{
var errorsToRemove = new Dictionary<int, ErrorOccurrenceDetails>();
foreach (Error error in this.errors)
{
int index = this.errors.IndexOf(error);
var listOfSearchedItems = error.Occurences.ToList();
listOfSearchedItems.RemoveAll(x => x.Times.Values.Any(y => y.Version != filterVersion));
var errorOccurences = error.Occurences.Except(listOfSearchedItems).ToList();
if (errorsToRemove.ContainsKey(index))
{
errorsToRemove[index].AddRange(errorOccurences);
}
else
{
errorsToRemove.Add(index, errorOccurences);
}
}
}
我正在尝试将所有需要删除的错误放入 errorsToRemove
字典中,其中 key 是 this.errors
中的错误索引,value 是未在搜索版本中出现的列表。
它有点有效,但有时不会删除坏版本并导致一些正确版本也被删除,所以有一个我没有注意到的漏洞。
此小提琴中的示例错误列表: https://dotnetfiddle.net/Kxq50i
答案 0 :(得分:1)
根据 Heinzi 的回答,我决定使用更简单的方法。我想我想不惜一切代价避免 Collection was modified; enumeration operation may not execute
异常并开始做一些愚蠢的事情。
private IList<Error> errors;
private static void Filter(string filterVersion)
{
for (int index = 0; index < errors.Count; index++)
{
Error error = errors[index];
foreach (var occurrence in error.Occurrences)
{
var toRemove = occurrence.Times.Keys.Where(key => occurrence.Times[key].Version != filterVersion).ToList();
foreach (var key in toRemove)
{
occurrence.Times.Remove(key);
}
if (occurrence.Times.Count == 0)
{
errors[index] = null; // not deleted to prevent index shift, null is hidden in UI
}
}
}
}
解决方案已更新 in this fiddle。
答案 1 :(得分:0)
原因可能是以下几行可能会导致原始 error.Occurences
的项目被删除:
var listOfSearchedItems = error.Occurences.ToList();
listOfSearchedItems.RemoveAll(x => x.Times.Values.Any(y => y.Version != filterVersion));
尝试用下面的替换这两行:
var listOfSearchedItems = error.Occurences.Where(x => x.Times.Values.Any(y => y.Version == filterVersion)); // Note: Here we also replaced the "!=" with "=="
答案 2 :(得分:0)
在使用 Linq 时,更容易考虑包含的内容,而不是您想要删除的内容,然后以这种方式编写代码。例如:
private static IList<Error> Filter(string filterVersion)
{
var filtered = errors.Where(error => error.Occurrences.Any(occurrence => occurrence.Times.Any(kvp => kvp.Value.Version == filterVersion)))
.Select(error =>
{
return new Error
{
Occurrences = error.Occurrences
.Where(occurrence => occurrence.Times.Any(kvp => kvp.Value.Version == filterVersion))
.Select(occurrence =>
{
return new ErrorOccurrenceDetails
{
Times = new Dictionary<DateTime, ErrorTime>(occurrence.Times.Where(kvp => kvp.Value.Version == filterVersion))
};
})
.ToList()
};
})
.ToList();
return filtered;
}
这种方法的另一个可能的好处是您不会修改原始数据,因此您可以应用不同的过滤器而无需重新阅读。