Я мог улучшить этот метод с утиным вводом?

... список совпадений на основе всех значений ....

Существует IEnumerable, который делает именно то, что вы сказали
Enumerable. All

bool allForA = listC.All(c => listA.Contains(c));
if(allForA)
   return listA;
....

И, я не уверен, но, вероятно, также является лучшим вариантом с точки зрения производительности, потому что я предполагаю, что если элемент не найден, перечисление остановится и вернет false без необходимости перечисления всех элементов списка

РЕДАКТИРОВАТЬ : Out из любопытства я проверил подход «все» против «пересечения», и теперь я могу подтвердить, что «все» как минимум в три раза быстрее, чем «пересечение». (Конечно, я говорю о миллисекундах в цикле 1 миллион, поэтому вряд ли о чем беспокоиться, но, тем не менее, мне было любопытно)

Это пример работы внутри LinqPad (скажите, если что-то не так)

void Main()
{
    List listA = new List {1,2,3,4,5};
    List listB = new List {6,7,8,9,0};
    List listC = new List {1,3,4};

    int z = 0;
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for(int x = 0; x < 1000000; x++)
        if (listB.Intersect(listC).Count() == listC.Count())
            z++;
    sw.Stop();
    sw.ElapsedMilliseconds.Dump("INTERSECT => B");

    z = 0;
    sw = new Stopwatch();
    sw.Start();
    for (int x = 0; x < 1000000; x++)
        if(listC.All(c => listB.Contains(c)))
            z++;
    sw.Stop();
    sw.ElapsedMilliseconds.Dump("ALL => B");

    sw.Start();
    for (int x = 0; x < 1000000; x++)
        if (listA.Intersect(listC).Count() == listC.Count())
            z++;
    sw.Stop();
    sw.ElapsedMilliseconds.Dump("INTERSECT => A");

    z = 0;
    sw = new Stopwatch();
    sw.Start();
    for (int x = 0; x < 1000000; x++)
        if (listC.All(c => listA.Contains(c)))
            z++;
    sw.Stop();
    sw.ElapsedMilliseconds.Dump("ALL => A");

}

5
задан Brent Dillingham 16 October 2008 в 17:33
поделиться

3 ответа

Как Вы пишете, что этот метод должен зависеть от того, ожидаете ли Вы, что исключение будет брошено в ходе нормального выполнения программы. Если Вы хотите читаемое сообщение об исключении, потому что конечный пользователь мог бы видеть его, то бросок того вручную имеет смысл. Иначе я просто сделал бы что-то вроде этого:

def convert(hash)
    new_hash = {}
    hash.each_pair { |k,v| new_hash[ k.is_a?(Integer) ? k : k.id ] = v }
    return new_hash
end

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

У нас все еще есть явная проверка на целочисленные объекты, но этот вид случайного особого случая обычно приемлем, особенно при проверке на встроенные типы данных.

11
ответ дан 18 December 2019 в 13:20
поделиться

Утиный ввод является действительно просто детальной версией полиморфизма. На статически типизированном языке как Java необходимо было бы создать явный интерфейс, который сказал компилятору все методы, что конкретная переменная может принять. С динамическим языком как Ruby интерфейсы все еще существуют в абстрактном смысле, они просто неявны.

Проблемой является то, что Вы принимаете две различных структуры данных в один метод. Способ сделать утку, вводящую работу, состоит в том, чтобы потребовать, чтобы все объекты, которые передаются Вашему методу, повиновались тому же контракту (т.е. это всегда - хеш Целых чисел к [Нечто] объекты.) Процесс преобразования хеша с ключами Свойства в корректную структуру должен быть заданием клиентского кода. Это может быть сделано очень легко с простым классом обертки или функцией преобразования, состоящей из просто тела Вашего elseif пункта.

Нижняя строка, которая это до парня, называющего метод для проверки его параметров весь шарлатан путем метод, ожидает их шарлатану. Если они не делают, он - тот, которого потребность выяснить, как сделать его кряканье индейки как утка, не Вы.

3
ответ дан 18 December 2019 в 13:20
поделиться

То, что я хочу, должно удостовериться, что я заканчиваю с хешем, где ключи являются целым числом, представляющим идентификатор объекта ActiveRecord.

Необходимо, вероятно, проверить на это, когда Вы создаете/вставляете в хеш. Вы могли попробовать что-то вроде этого:

h = {}
def h.put obj
  self[obj.id]=obj
end

или возможно

h = {}
def h.[]= key, value
  raise "hell" unless key == value.id
  super
end
0
ответ дан 18 December 2019 в 13:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: