извлечь/нарезать/переупорядочить списки в (emacs) шепелявость?

В Python Вы могли бы сделать что-то как

i = (0, 3, 2)
x = [x+1 for x in range(0,5)]
operator.itemgetter(*i)(x)

добираться (1, 4, 3). В (emacs) шепелявость я записал эту функцию, вызванную извлечение, которое делает что-то подобное,

(defun extract (elems seq)
  (mapcar (lambda (x) (nth x seq)) elems))

(extract '(0 3 2) (number-sequence 1 5))

но я чувствую, что должно быть что-то, встроил? Все, что я знаю, first, last, rest, nth, car, cdr... Что состоит в том, чтобы пойти путь? ~ Заранее спасибо ~

6
задан hatmatrix 25 May 2010 в 00:26
поделиться

3 ответа

Если ваша проблема заключается в скорости, то используйте (vector 1 2 3 4 5) вместо списка, и (aref vec index) для получения элемента.

(defun extract (elems seq)
  (let ((av (vconcat seq)))
    (mapcar (lambda (x) (aref av x)) elems)))

Если вы собираетесь извлекать из одной и той же последовательности много раз, конечно, имеет смысл хранить последовательность в векторе только один раз. Списки в Python действительно являются одномерными массивами, эквивалентом в LISP являются векторы.

4
ответ дан 17 December 2019 в 00:04
поделиться

Из Мои впечатления от Lisp и разработка GNU Emacs :

В те дни, в 1985 году, были люди, у которых были машины размером в один мегабайт без виртуальной памяти. Они хотели иметь возможность использовать GNU Emacs. Это означало, что я должен был сделать программу как можно меньше.

Например, в то время единственной циклической конструкцией было «while», что было чрезвычайно просто. Невозможно было прервать выполнение оператора while, вам просто нужно было выполнить catch и throw или протестировать переменную, которая запускала цикл. Это показывает, как далеко я зашел, чтобы все было маленьким. У нас не было «caar», «cadr» и так далее; «Выжать все возможное» было духом GNU Emacs, духом Emacs Lisp с самого начала.

Очевидно, что машины сейчас больше, и мы больше так не делаем. Мы добавляем «caar», «cadr» и т. Д., И, возможно, однажды мы добавим еще одну циклическую конструкцию.

Я предполагаю, что если вы этого не видите, значит, его там нет.

1
ответ дан 17 December 2019 в 00:04
поделиться

Я делал только простые сценарии на elisp, но это относительно небольшой язык. И extract - это очень неэффективная функция для связных списков, которые являются структурой данных по умолчанию в emacs lisp. Поэтому она вряд ли будет встроенной.

Ваше решение - лучшее прямолинейное решение. Оно n^2, но чтобы сделать его быстрее, требуется гораздо больше кода.

Ниже приведено предположение, как это может работать, но оно может быть и совершенно неверным:

  1. отсортировать elems (n log n)
  2. создать карту, которая отображает элементы в отсортированном elem на их индексы в исходном elem (вероятно, n log n, возможно n)
  3. итерация через seq и отсортированный elem. Сохраните только индексы в отсортированном elem (возможно n, возможно n log n, в зависимости от того, хэш-карта это или древовидная карта)
  4. отсортируйте результат по значениям отображения elem (n log n)
2
ответ дан 17 December 2019 в 00:04
поделиться
Другие вопросы по тегам:

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