LINUX.ORG.RU

[ФП][Морфизмы] Годная задачка про списки :)


0

0

Нашёл такую штуку:

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

Какие могут быть решения? Циклы vs. Рекурсия vs. Морфизмы?

Пришлось убить минут двадцать :) Но морфизм есть.

★★★★

Предлагаю нормальное решение

1) найти библиотеку решающую задачу

2) найти язык программирования который содержить решение в виде одного оператора

3) найти студента

wfrr ★★☆
()

кортеж, т.е. гетерогенный список, - и есть функция предикат для его элементов

и какой у этой функции тип?

jtootf ★★★★★
()

Циклы vs. Рекурсия vs. Морфизмы?

но вообще вопрос у тебя потрясный, конечно. я это «vs морфизмы» запомню

jtootf ★★★★★
()

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

Можно проходить по списку рекурсивно.

anonymous
()

Пришлось убить минут двадцать

Ты наркоман щтоле?

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

btw:

(defun split-list (list p)
  (loop :for el :in list
        :when (funcall p el) :collect el :into l1
        :else :collect el :into l2
        :finally (return (values l1 l2))))

Love5an
()

> Пришлось убить минут двадцать :) Но морфизм есть.

в цитатки

Sphinx ★★☆☆
()
Ответ на: комментарий от korvin_

Судя по твоей и его аватаркам, в этом треде царит морфизм.

anonymous
()
Ответ на: комментарий от arhibot

Ого. И что оно делает? Режет список по предикату, как и нужно ТС?

// каждым таким постом ты меня всё больше и больше заинтересовываешь Ерлангом :)

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

«Partitions List into two lists, where the first list contains all elements for which Pred(Elem) returns true, and the second list contains all elements for which Pred(Elem) returns false.»

arhibot
()
Ответ на: комментарий от jtootf

А тем временем лисперы, что-то на циклах выдумывают

arhibot
()
Ответ на: комментарий от Love5an

показательный пример

ты, как всегда, видишь только то, что тебе хочется увидеть; может, очки стоит заказать?

jtootf ★★★★★
()
Ответ на: комментарий от Love5an
> def split_it (l, p):
  return (
   [i for i in filter (p, l)],
   [i for i in filter (lambda x: not p(x), l)]
  )
> split_it (range(6), lambda x: x%2==0)
([0, 2, 4], [1, 3, 5])

господа питонщики, как элегантнее отделить вторую половину списка, не подпадающую под предикат?

val-amart ★★★★★
()
Ответ на: комментарий от val-amart

>[i for i in filter (p, l)]

мне казалось, что лучше либо filter, либо [i for i in list if i > 3]


p.s. в моей книге изучаем питон написано, что filter собственно устарел и не надо его юзать.

dimon555 ★★★★★
()
Ответ на: комментарий от val-amart

господа питонщики, как элегантнее отделить вторую половину списка

да кто же его знает

вот некрасиво

In [10]: def split_it(l,p):
   ....:     l1 = []
   ....:     l2 = []
   ....:     for x in l:
   ....:         if p(x):
   ....:             l1.append(x)
   ....:         else:
   ....:             l2.append(x)
   ....:     return (l1,l2)
   ....: 

In [11]: split_it (range(6), lambda x: x%2==0)
Out[11]: ([0, 2, 4], [1, 3, 5])

dimon555 ★★★★★
()
Ответ на: комментарий от balodja

Нет, не слишком.

В самый раз. Кроме того, еще и очень наглядное и простое к пониманию решение.

Но для особо упоротых можно сделать и по-другому, конечно:

(defun split-list (l p &aux l2)
  (~ (filter (! (-> (or {p _} [(>> _ l2) nil]))) l) l2))
p.s.
(defmacro -> (&body body)
  `(lambda (,(intern "_" *package*)) ,@body))

(defun filter (predicate sequence &key from-end (start 0) end count key)
  (remove-if predicate sequence
             :from-end from-end
             :start start
             :end end
             :count count
             :key key))

(defun ~ (&rest args) (apply #'values args))

(defmacro >> (obj place)
  (let ((x (gensym)) (l (gensym "LIST")))
    `(let ((,x ,obj) (,l ,place))
       (if (null ,l)
         (setf ,place (cons ,x nil))
         (setf (cdr (last ,l)) (cons ,x nil))))))

(defun ! (function)
  (complement function))

(set-macro-character #\{
  (lambda (s c)
    (declare (ignore c))
    (let ((form (read-delimited-list #\} s t)))
      `(funcall ,@form))))

(set-macro-character #\}
  (lambda (s c)
    (declare (ignore s c))
    (error "Unmatched close brace")))

(set-macro-character #\[
  (lambda (s c)
    (declare (ignore c))
    (let ((form (read-delimited-list #\] s t)))
      `(progn ,@form))))

(set-macro-character #\]
  (lambda (s c)
    (declare (ignore s c))
    (error "Unmatched close bracket")))

Love5an
()
Ответ на: комментарий от arhibot

> > С каких пор кортеж — это гетерогенный список?

во всяком случае как минимум в MLях так.

Тогда второй вопрос: с каких пор в ML'ях кортеж — рекурсивный ADT?

balodja ★★★
()
Ответ на: комментарий от Love5an

можно же не заморачиваться и сделать через remove-if/remove-if-not

(values (remove-if #'oddp mylist) (remove-if-not #'oddp mylist))

убил секунд 20!

но ТС норкоман

lazyklimm ★★★★★
()
Ответ на: комментарий от lazyklimm

...и получаем два прохода по списку место одного

yoghurt ★★★★★
()

>> Есть список - точнее кортеж, т.е. гетерогенный список,

Так что же все таки есть?

cathode
()
Ответ на: комментарий от alix

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

val-amart ★★★★★
()
Ответ на: комментарий от dimon555

ты прав, это полная чушь. надо просто filter. кстати, насчет устарел: он фактически просто был заменен аналогом из итертулс, я делаю один импорт в начале:
from itertools import ifilter as filter

val-amart ★★★★★
()
def split_list(f, xs):
    result = [[], []]
    [result[f(x)].append(x) for x in xs]
    return result   

Значительно лучше чем оба варианта на CL.

tarc
()
Ответ на: комментарий от tarc
def split_list(f, xs): 
    result = [[], []] 
    [result[f(x)].append(x) for x in xs] 
    return result    

Значительно лучше чем оба варианта на CL.

Не соглашусь, что лучше. Пользоваться такими вот эффектами

>>> a = [[1,2],[3,4]] 
>>> a[False]
[1, 2]
>>> a[True]
[3, 4]
>>> 

ИМХО есть безобразие

EVP
()
Ответ на: комментарий от EVP

> ИМХО есть безобразие

Это только твои предрассудки.

каким местом лучше?

Проще и понятнее чем оба твоих варианта.

tarc
()
Ответ на: комментарий от tarc

Проще и понятнее чем оба твоих варианта.

Мой второй вариант это просто прикол(пояснение для тех, кому трудно доходит, да). А первый - это буквально псевдокод. Самый простой, эффективный и понятный вариант из возможных.

И ты говоришь, что вот это вот нагромождение говна проще и понятнее моего варианта:

result = [[], []]
[result[f(x)].append(x) for x in xs]  

Поэтому я повторю вопрос.

Love5an
()
Ответ на: комментарий от tarc

И, это самое.

Это только твои предрассудки.

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

Love5an
()
Ответ на: комментарий от jtootf

а это какой язык?

На руби похоже.

Вброшу по такому случаю на факторе:

100 [0,b] [ odd? ] partition

anonymous
()
Ответ на: комментарий от Love5an

Что ты понимаешь под понятностью? Мне даже не ясно, что ожидать из твоей функции на выходе. Где указано, что l1 и l2 - это именно списки, а не, например, множества? Не понятно, что делает оператор :collect - он кладет элементы в начало списка? в конец? В отличае от «append» в моем варианте, твой «collect» о порядке ничего не говорит.

tarc
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.