2014-01-09 4 views
3

Проблема в том, что у меня есть два списка строк. Один список - это приближение другого списка, и мне нужен какой-то способ измерения точности приближения.Сравнение двух упорядоченных списков в C#

Как временный способ подсчета аппроксимации, я собрал каждый список (аппроксимация и ответ) в 3 раздела (высокий, средний минимум) после сортировки на основе числового значения, соответствующего строке. Затем я сравниваю все элементы в приближении, чтобы увидеть, существует ли строка в том же разделе правильного списка.

Я суммирую количество правильно классифицированных строк и деля их на общее количество строк. Я понимаю, что это очень грубый способ измерения точности оценки, и надеялся, что будут доступны лучшие альтернативы. Это очень маленький компонент большей части работы, и он надеялся не изобретать колесо.

EDIT: Я думаю, что я был недостаточно ясен. Мне не нужны два одинаковых списка, мне нужна какая-то мера, которая показывает, что списки похожи. Например, подход «Высокий средний-низкий» (H-M-L), который мы использовали, показывает, что оценочный список достаточно схож. Недостатком этого подхода является то, что если в оценочном списке есть элемент в нижней части скобки «Высокий», а в фактическом списке элемент находится в верхней части набора средств, алгоритм оценки не может выполнить.

Вполне возможно, что в дополнение к подходу H-M-L нижние 20% каждой секции сравниваются с верхними 20% следующего раздела или чем-то вдоль этих строк.

Спасибо всем за помощь!

+10

Как насчет размещения соответствующего кода вместо * описания * его? Вместе с входным, выходным и * ожидаемым выходом *. –

+1

Можете ли вы разместить свой код? – AymenDaoudi

+0

Звучит как полное внешнее соединение. Дифференциальные списки всегда являются полным внешним соединением. – usr

ответ

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; 
+1

. Вы считаете, что списки имеют одинаковую длину. Я не думаю, что это дано. – usr

+0

@usr Из того, что описал ОП ... Я не знаю точно, как иначе это будет работать. – Andrew

+0

Я не знаю точно, что описал ОП. Мой подход: дождитесь разъяснения (или закройте). – usr

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 определяют уровень равенства. В моем примере процент.

Если вы сравните эти 2 списка, вы получите 75% от равенства, то же самое, что 3 из 4 равных элементов (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); 

Надеюсь, это поможет.

+0

Ваш метод CompareTwoLists может быть просто реализован как 'list1.Intersect (list2) .Count();' – Servy

+0

Да, вы правы. Спасибо за исправление. –

+0

Спасибо за это, а не за ответ, но часть контента полезна для улучшения моей существующей реализации! Огромное спасибо. –

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); 
} 
+0

Это код для вашего вопроса? или ответ? –

+0

@AlbertoMontellano Для ответа. – Servy

+0

Я думаю, что ваш ответ правильный. Но не такая же логика для решения проблемы такая же, что и вопрос? он просит другого? –

Смежные вопросы