[英]Linq count number of differences in lists in a collection
I want to count the number of differences (or similarities) in lists within a collection.The following code is a for loop which produces the right results, comparing every other record with the first record. 我想计算集合中列表中的差异(或相似性)的数量。以下代码是for循环,它产生正确的结果,将每个其他记录与第一个记录进行比较。 Is there a way to do it better? 有没有办法做得更好? With Linq, perhaps? 或许Linq?
public void Main(){
_records = new ObservableCollection<Record>();
_records.Add(new Record { Name = "Correct", Results = new List<string> { "A", "B","C" } , Score="100%"} );
_records.Add(new Record { Name = "John", Results = new List<string> { "A", "B" ,"C" } } ); //Expect score to be 3/3 (100%)
_records.Add(new Record { Name = "Joseph", Results = new List<string> { "A", "C","B" } }); //Expect score to be 2/3 (67%)
_records.Add(new Record { Name = "James", Results = new List<string> { "C", "C", "C" } }); //Expect score to be 1/3 (33%)
for(int i = 1; i < _records.Count(); i++) // Each Results in the _records except "Correct"
{
float score = _records[0].Results.Count();
_records[i].Score = string.Format("{0:p1}", (score - CountDifferences(_records[i].Results, _records[0].Results) ) / score );
}
}
private int CountDifferences(List<string> x, List<string> y)
{
return (x.Zip(y, (a, b) => a.Equals(b) ? 0 : 1).Sum());
}
I would go about doing it like this: 我会这样做:
var results =
from r0 in _records.Take(1)
from r in _records
let score = (double)r0.Results.Count()
let differences = CountDifferences(r.Results, r0.Results)
select new { record = r, score = ((score - differences) / score).ToString("p1") };
foreach (var result in results)
{
result.record.Score = result.score;
}
I would, hovever suggest that you do not have .Score
as a property of Record
as a score is only valid when you can compare one record against another. 我想,霍夫表示你没有.Score
作为Record
的属性作为分数只有当你可以比较一个记录与另一个记录时才有效。 That would mean that if you have three separate results the score could be different if you compare against either of the other two. 这意味着如果您有三个单独的结果,如果您与其他两个中的任何一个进行比较,那么得分可能会有所不同。
So I would suggest this: 所以我建议这样做:
public class Record
{
public string Name;
public List<string> Results;
public double GetScore(Record benchmark)
{
var max = benchmark.Results.Count;
var differences = benchmark.Results
.Zip(this.Results, (a, b) => a == b)
.Where(r => r == false)
.Count();
return ((double)max - differences) / max;
}
}
Then just do this query to get the results: 然后只需执行此查询即可获得结果:
var results =
from r0 in _records.Take(1)
from r in _records
select new
{
record = r,
score = r.GetScore(r0).ToString("p1")
};
That gives me: 这给了我:
I made the LINQ (with lambda expressions) statement work off a dictionary that uses the students' name as the key and custom class Record as the value. 我将LINQ(带有lambda表达式)语句用于使用学生名称作为键并使用自定义类Record作为值的字典。 Then compare that against a separate List the grades are expected to be. 然后将其与单独的列表进行比较,预期成绩。
List<string> expected = new List<string>(){"A", "B","C" };
Dictionary<string, Record> _records = new Dictionary<string, Record>();
_records["John"] = new Record { Name = "John", Results = new List<string> { "A", "B" ,"C" } } ;
_records["Joseph"]= new Record { Name = "Joseph", Results = new List<string> { "A", "C","B" } } ;
_records["James"] = new Record { Name = "James", Results = new List<string> { "C", "C", "C" } } ;
foreach(var v in _records){
decimal count = v.Value.Results.Where((x,index) => expected[index]==x).Count()/(decimal)expected.Count();
v.Value.Score = String.Format("{0:P0}",count);
}
foreach(var v in _records)
Console.WriteLine("{0} {1}",v.Value.Name,v.Value.Score);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.