比较C#中的两个有序列表

时间:2014-01-09 20:58:42

标签: c# performance list-comparison

问题是我有两个字符串列表。一个列表是另一个列表的近似值,我需要一些方法来测量近似值的准确性。

作为对近似值进行评分的临时方法,我在根据与字符串对应的数值进行排序后,将每个列表(近似值和答案)分成3个分区(高,中低)。然后我比较了近似中的所有元素,看看字符串是否存在于正确列表的同一分区中。

我将正确分类的字符串的数量相加并将其除以字符串的总数。我知道这是衡量估算准确性的一种非常粗略的方法,并希望有更好的替代方案。这是较大工作的一个非常小的组成部分,并且希望不必重新发明轮子。

编辑: 我觉得我不够清楚。我不需要两个列表完全相同,我需要某种措施来显示列表是相似的。例如,我们采用的高 - 中 - 低(H-M-L)方法表明估计列表足够相似。这种方法的缺点是,如果估计列表在“高”括号的底部有一个项目,并且在实际列表中,该项目位于中等集合的顶部,则分数算法无法提供。

除了H-M-L方法之外,还可能是每个分区的最低20%与下一个分区的前20%或沿着这些线的东西进行比较。

谢谢大家的帮助!!

3 个答案:

答案 0 :(得分:1)

好问题。好吧,我认为您可以使用以下方法来比较您的列表:

 public double DetermineAccuracyPercentage(int numberOfEqualElements, int yourListsLength)
    {
        return ((double)numberOfEqualElements / (double)yourListsLength) * 100.0; 
    }

返回的数字应确定两个列表之间存在多少相等性。 如果numberOfEqualElements = yourLists.Length(Count),那么它们绝对相等。 近似的准确性=(numberOfEqualElements / yourLists.Length) 1 =完全相等,0 =绝对不同,0和1之间的值决定了相等程度。在我的样本中,百分比。

如果你比较这两个列表,你将检索75%的相等,与4个相等元素中的3个相同(3/4)。

        IList<string> list1 = new List<string>();
        IList<string> list2 = new List<string>();

        list1.Add("Dog");
        list1.Add("Cat");
        list1.Add("Fish");
        list1.Add("Bird");

        list2.Add("Dog");
        list2.Add("Cat");
        list2.Add("Fish");
        list2.Add("Frog");


          int resultOfComparing = list1.Intersect(list2).Count();
        double accuracyPercentage = DetermineAccuracyPercentage(resultOfComparing,   list1.Count); 

我希望它有所帮助。

答案 1 :(得分:1)

因此,我们采用一系列项目并将其分组为三个类别,分别为高,中,低三个类别。让我们首先创建一个对象来表示这三个分区:

public class Partitions<T>
{
    public IEnumerable<T> High { get; set; }
    public IEnumerable<T> Medium { get; set; }
    public IEnumerable<T> Low { get; set; }
}

接下来做一个估计我们想要取两个这样的对象,一个用于实际,一个用于估计。对于每个优先级,我们希望看到两个集合中有多少项;这是一个“交叉点”;我们想要总结每组交集的计数。

然后将该数除以总数:

public static double EstimateAccuracy<T>(Partitions<T> actual
    , Partitions<T> estimate)
{
    int correctlyCategorized = 
        actual.High.Intersect(estimate.High).Count() +
        actual.Medium.Intersect(estimate.Medium).Count() +
        actual.Low.Intersect(estimate.Low).Count();

    double total = actual.High.Count()+
        actual.Medium.Count()+
        actual.Low.Count();

    return correctlyCategorized / total;
}

当然,如果我们将其概括为3个优先级,而不是一系列序列,其中每个序列对应一些桶(即有N个桶,而不仅仅是3个),代码实际上变得更容易:

public static double EstimateAccuracy<T>(
    IEnumerable<IEnumerable<T>> actual
    , IEnumerable<IEnumerable<T>> estimate)
{
    var query = actual.Zip(estimate, (a, b) => new
    {
        valid = a.Intersect(b).Count(),
        total = a.Count()
    }).ToList();
    return query.Sum(pair => pair.valid) /
        (double)query.Sum(pair => pair.total);
}

答案 2 :(得分:0)

我会同时使用List<String>并将每个元素组合成IEnumerable<Boolean>

public IEnumerable<Boolean> Combine<Ta, Tb>(List<Ta> seqA, List<Tb> seqB)
{
  if (seqA.Count != seqB.Count)
    throw new ArgumentException("Lists must be the same size...");

  for (int i = 0; i < seqA.Count; i++)
    yield return seqA[i].Equals(seqB[i]));
}

然后使用Aggregate()来验证哪些字符串匹配并保持运行总计:

var result = Combine(a, b).Aggregate(0, (acc, t)=> t ? acc + 1 : acc) / a.Count;