Повышение производительности при получении повторяющихся телефонных номеров в ABAddressBook

Я работаю над приложением для iPhone, которое позволяет получить дубликаты телефонных номеров. Я уже сделал код, но производительность настолько плохая и требует времени. Вот мой код:

    OrderedDictionary persons = new OrderedDictionary ();
    ABAddressBook ab = new ABAddressBook ();

    foreach (ABPerson p in ab.GetPeople()) {

            foreach (var phoneNumber in p.GetPhones().GetValues()) {
                var duplicates = SearchByPhoneNumber (ab, phoneNumber);
                if (duplicates.Count > 1) {
                    if (!persons.Contains (phoneNumber)) {
                        persons.Add (phoneNumber, duplicates);
                    }
                }

            }
        }


    List<ABPerson> SearchByPhoneNumber ( ABAddressBook ab, string phoneNumber)
{
        List<ABPerson> duplicatepeople = new List<ABPerson> ();
        phoneNumber = Regex.Replace (phoneNumber, "[^0-9]", "");


        var people = ab.Where(x=> x is ABPerson).Cast<ABPerson>().Where(x=> x.GetPhones()
                                                                        .Where(p=> Regex.Replace(p.Value,"[^0-9]", "")==phoneNumber || phoneNumber ==Regex.Replace(p.Value,"[^0-9]", "")).Count() > 0).ToArray();

        foreach(ABPerson person in people)
        {
            if( duplicatepeople.Intersect(person.GetRelatedNames().Cast<ABPerson>()).Count() <= 0)
            {
                duplicatepeople.Add(person);
            }

        }

        return duplicatepeople;
    }

person Ahmed Mohamed Anas    schedule 06.02.2013    source источник


Ответы (1)


У меня не было времени проверить тайминги между ними, но я заметил, что вы повторяете номера адресной книги несколько раз (для каждого номера телефона вы снова итерируете список с каждым .Where). Также я заметил, что вы выполняете одно и то же регулярное выражение для каждого номера телефона несколько раз в циклах.

Возможно, это не совсем соответствует вашим потребностям, но оно нашло дубликаты в моей адресной книге и не было слишком медленным.

ABAddressBook ab = new ABAddressBook();

// flatten out the list of all phone numbers and perform the regEx just once for each phone number
var processedList = new List<Tuple<string, ABPerson>>();
foreach (ABPerson p in ab.GetPeople()) 
{
    foreach (var phoneNumber in p.GetPhones().GetValues()) 
    {
        processedList.Add(new Tuple<string, ABPerson>(Regex.Replace (phoneNumber, "[^0-9]", ""), p));
    }
}

var duplicates = (from person in processedList
    group person by person.Item1 into g
    where g.Count() > 1
    select new { PhoneNumber = g.Key, Person = g }).ToList();

foreach (var d in duplicates)
{
    Console.WriteLine("{0}  {1}", d.PhoneNumber, d.Person.Count());
    foreach (var p in d.Person)
    {
        Console.WriteLine(p.Item2.FirstName);
    }
}

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

person Greg Munn    schedule 10.02.2013
comment
Большое спасибо, я уже решил ... но все же ваш ответ правильный :) - person Ahmed Mohamed Anas; 23.02.2013