我正在尝试解析一个相当长的日志文件,并创建一个更易于管理的问题列表。
我能够逐行读取和解析单个日志,但我需要做的只是显示唯一条目,因为有些错误比其他错误更频繁地发生,并且总是用相同的文本记录。
我要尝试做的是创建一个Dictionary对象来保存每个唯一条目,当我处理日志文件时,搜索Dictionary对象以查看是否已存在相同的值。
以下是我所拥有的代码的原始示例(正在进行中的工作,我希望我的所有语法都正确),但这些代码不起作用。由于某种原因,此脚本永远不会看到任何不同的条目(if语句永远不会通过):
string[] rowdta = new string[4];
Dictionary<string[], int> dict = new Dictionary<string[], int>();
int ctr = -1;
if (linectr == 1)
{
ctr++;
dict.Add(rowdta, ctr);
}
else
{
foreach (KeyValuePair<string[], int> pair in dict)
{
if ((pair.Key[1] != rowdta[1]) || (pair.Key[2] != rowdta[2])| (pair.Key[3] != rowdta[3]))
{
ctr++;
dict.Add(rowdta, ctr);
}
}
}
一些示例数据: 第一行
rowdta[0]="ErrorType";
rowdta[1]="Undefined offset: 0";
rowdta[2]="/url/routesDisplay2.svc.php";
rowdta[3]="Line Number 5";
第二行
rowdta[0]="ErrorType";
rowdta[1]="Undefined offset: 0";
rowdta[2]="/url/routesDisplay2.svc.php";
rowdta[3]="Line Number 5";
第3行
rowdta[0]="ErrorType";
rowdta[1]="Undefined variable: fvmsg";
rowdta[2]="/url/processes.svc.php";
rowdta[3]="Line Number 787";
因此,通过此,词典中将包含2个项目,第一行和第三行。
我也尝试过以下内容,nalso在日志文件文本中找不到任何变化。
if (!dict.ContainsKey(rowdta)) {}
有人可以帮我解决这个问题吗?我只是C#的新手,但这应该是相对简单的。和往常一样,我认为这应该是足够的信息来开始对话。如果您需要/需要更多细节,请告诉我。
答案 0 :(得分:1)
您看到问题的原因是,如果没有提供自定义IEqualityComparer<string[]>
或在其周围编写包装器,则字符串数组不能用作字典中的键。
编辑以下是自定义比较器的快速而又脏的实现:
private class ArrayEq<T> : IEqualityComparer<T[]> {
public bool Equals(T[] x, T[] y) {
return x.SequenceEqual(y);
}
public int GetHashCode(T[] obj) {
return obj.Sum(o => o.GetHashCode());
}
}
以下是如何使用它:
var dd = new Dictionary<string[], int>(new ArrayEq<string>());
dd[new[] { "a", "b" }] = 0;
dd[new[] { "a", "b" }]++;
dd[new[] { "a", "b" }]++;
Console.WriteLine(dd[new[] { "a", "b" }]);
答案 1 :(得分:1)
为字符串创建一个包装器,它实现IEquatable。
public class LogFileEntry :IEquatable<LogFileEntry>
{
private readonly string[] _rows;
public LogFileEntry(string[] rows)
{
_rows = rows;
}
public override int GetHashCode()
{
return
_rows[0].GetHashCode() << 3 |
_rows[2].GetHashCode() << 2 |
_rows[1].GetHashCode() << 1 |
_rows[0].GetHashCode();
}
#region Implementation of IEquatable<LogFileEntry>
public override bool Equals(Object obj)
{
if (obj == null)
return base.Equals(obj);
return Equals(obj as LogFileEntry);
}
public bool Equals(LogFileEntry other)
{
if(other == null)
return false;
return _rows.SequenceEqual(other._rows);
}
#endregion
}
然后在你的词典中使用它:
var d = new Dictionary<LogFileEntry, int>();
var entry = new LogFileEntry(rows);
if( d.ContainsKey(entry) )
{
d[entry] ++;
}
else
{
d[entry] = 1;
}
或者创建一个类似于@dasblinkenlight提出的自定义比较器,并使用如下
public class LogFileEntry
{
}
public class LogFileEntryComparer : IEqualityComparer<LogFileEntry>{ ... }
var d = new Dictionary<LogFileEntry, int>(new LogFileEntryComparer());
var entry = new LogFileEntry(rows);
if( d.ContainsKey(entry) )
{
d[entry] ++;
}
else
{
d[entry] = 1;
}
答案 2 :(得分:0)
问题是数组相等是引用相等。换句话说,它不依赖于存储在数组中的值,它只取决于数组的标识。
一些解决方案
Tuple
来保存行数据