Вид Python параллелен массивам на месте?

Существует ли легкое (значение, не прокручивая собственную функцию сортировки) способ отсортировать параллельные списки без ненужного копирования в Python? Например:

foo = range(5)
bar = range(5, 0, -1)
parallelSort(bar, foo)
print foo # [4,3,2,1,0]
print bar # [1,2,3,4,5]

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

6
задан dsimcha 8 February 2010 в 15:49
поделиться

4 ответа

Есть ли простой способ? Да. Используйте молнию.

Есть ли «простой способ, не использующий вариант zip»? Нет.

Если бы вы хотели подробнее объяснить, почему вы возражаете против использования zip, это было бы полезно. Либо вы копируете объекты, и в этом случае Python будет копировать по ссылке, либо вы копируете что-то настолько легкое в легкий кортеж, что не заслуживает оптимизации.

Если вас действительно не волнует скорость выполнения, но по какой-то причине вас особенно беспокоит нехватка памяти, вы можете использовать собственную пузырьковую сортировку (или выбранный алгоритм сортировки) в списке ключей, который меняет местами как список ключей, так и цель перечисляет элементы при замене. Я бы назвал это противоположностью легкости, но это определенно ограничит ваш рабочий набор.

3
ответ дан 10 December 2019 в 02:47
поделиться

Лично я думаю, что это недостаток в дизайне Java. Да, да, я понимаю, что нестатические методы присоединены к экземпляру, а статические методы присоединены к классу и т.д. Однако рассмотрим следующий код:

public class RegularEmployee {
    private BigDecimal salary;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }

    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }

    public BigDecimal calculateBonus() {
        return salary.multiply(getBonusMultiplier());
    }

    /* ... presumably lots of other code ... */
}

public class SpecialEmployee extends RegularEmployee {
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".03");
    }
}

Этот код не будет работать так, как можно было бы ожидать. А именно, SpecityEmployee получает бонус в 2% так же, как и обычные сотрудники. Но если удалить «статические», то SpecureEmployee получит бонус 3%.

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

Мне кажется вполне правдоподобным, что вы могли бы сделать getPortingMultiplier статичным. Возможно, необходимо иметь возможность просмотра множителя бонуса для всех категорий сотрудников без необходимости иметь экземпляр сотрудника в каждой категории. Какова будет точкой поиска таких примеров? Что делать, если создается новая категория сотрудников, которой еще не присвоены сотрудники? Это вполне логично статическая функция.

Но это не работает.

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

Возможно, если бы я попытался написать компилятор для языка ООП, я бы быстро увидел, почему его реализация, чтобы статические функции могли быть переопределены, была бы трудной или невозможной.

Или, возможно, есть какая-то веская причина, почему Java ведет себя так. Может ли кто-нибудь указать на преимущество такого поведения, какой-то категории проблем, которая облегчается этим? Я имею в виду, не просто указать мне на язык Java и сказать «смотрите, это документировано, как он ведет себя». Я знаю это. Но есть ли веская причина, почему он ДОЛЖЕН вести себя так путь?

Обновление

@ VicKirk: Если вы имеете в виду, что это «плохой дизайн», потому что он не подходит для того, как Java обрабатывает статику, мой ответ: «Ну, duh, конечно.» Как я сказал в своем первоначальном посте, это не работает. Но если вы имеете в виду, что плохой дизайн в том смысле, что было бы что-то принципиально неправильное с языком, где это работало, т.е. где статика могла бы быть переопределена так же, как виртуальные функции, что это как-то ввело бы двусмысленность или было бы невозможно эффективно реализовать или какой-то такой, я отвечаю: "Почему? Что плохого в этой концепции? "

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

-121--1796173-

Помимо очевидного (реализация виртуальной машины), некоторые типы задач требовали довольно глубокого понимания IL.

  • Запись динамического кода. Это было довольно хорошо заменено API System.Linq.Expressions, особенно учитывая его способности в .NET 4.
  • Создание компилятора для нового языка, предназначенного для интерфейса командной строки. Такие проекты, как Common Compiler Infrastructure , направлены на уменьшение количества записей, которые должны быть записаны компиляторами кода CIL.

Один из самых интересных аспектов для меня лично - изучение влияния языка IL на компилятор только что. Один примечательный пример, контрастирующий с JVM и CLI, состоит в том, что CLI имеет понятие невиртуальных методов и прямой рассылки, что позволяет особенно эффективным вызовам излучаться неоптимизирующим (базовым) компилятором. Этот анализ является более дорогостоящим в JVM, поэтому компилятор базовой линии не может оптимизировать столько случаев.

В ответ на первоначальный вопрос:

В целом разработчикам .NET не нужно беспокоиться об изучении CIL. Если работа включает в себя выполнение/динамически генерируемые методы, то следует оценить способность API Expressions удовлетворять ваши потребности, так как он чрезвычайно более пригоден для использования/обслуживания. Я провел несколько недель, выделяя CIL с ILGenerator. Мне понадобилось одно время, чтобы преобразовать в Выражения, сохранив более сотни строк кода и исправив старые ошибки, которые я просто не понял.

Подробное знание CIL очень важно для всех, кто реализует виртуальную машину CLI или пишущих компиляторов (AOT или JIT). Я нахожу это как интересным, так и полезным, но в области «важных вещей, чтобы знать, чтобы быть продуктивным разработчиком», это просто не так высоко.

-121--26693-

Вот простой способ:

perm = sorted(xrange(len(foo)), key=lambda x:foo[x])

Это создает список перестановок - значение в perm [i] является индексом i-го наименьшего значения в foo. Затем, вы можете получить доступ к обоим спискам в порядке:

for p in perm:
  print "%s: %s" % (foo[p], bar[p])

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

6
ответ дан 10 December 2019 в 02:47
поделиться

Чтобы добиться этого, вам придется реализовать свою собственную сортировку.

Однако: действительно ли ненужное копирование вредит вашему приложению? Часто части Python тоже кажутся мне неэффективными, но они достаточно эффективны для того, что мне нужно.

0
ответ дан 10 December 2019 в 02:47
поделиться

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

Если это действительно проблема, могут быть более эффективные решения. Поскольку элементы foo и bar так тесно связаны, уверены ли вы, что их правильное представление не является списком кортежей? Вы уверены, что они не должны находиться в более компактной структуре данных, если у вас заканчивается память, например, в массиве numpy или базе данных (последняя из которых действительно хороша для такого рода манипуляций)?

(Кроме того, кстати, itertools.izip может сэкономить вам немного памяти по сравнению с zip , хотя в результате вы все равно получаете полный заархивированный список в виде списка в результате сортировки.)

0
ответ дан 10 December 2019 в 02:47
поделиться
Другие вопросы по тегам:

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