LINUX.ORG.RU

Работа с последовательностями в разных языках

 , , , ,


7

9

Навеяно темой Ментальный вирус, пример взят и дополнен оттуда. Интересует реализация подобной операции на других языках. Лично я хотел бы увидеть на Lisp, Java, Smalltalk, Erlang.

array = ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]

puts array.select{|v|v[/^J[a-z]+/]}. # ВЫБРАТЬ ПО someregexp
each_slice(3). # КАЖДЫЙ КУСОК ПО 3 ЭЛЕМЕНТА
map{|v| "#{v[0]} and #{v[1]} follow #{v[2]}"}. # ПОДСТАВИТЬ ЗНАЧЕНИЯ В СТРОКУ
join("\n") # ОБЪЕДИНИТЬ
# John and James follow Jakob
# Janette and Jean follow Juilia

Пошагово для тех, кто не знаком с Ruby:

array.select{|v|v[/^J[a-z]+/]}
# ["John", "James", "Jakob", "Janette", "Jean", "Juilia"]
array.select{|v|v[/^J[a-z]+/]}.
each_slice(3).to_a # в массив
# [["John", "James", "Jakob"], ["Janette", "Jean", "Juilia"]]
array.select{|v|v[/^J[a-z]+/]}.each_slice(3).
map{|v| "#{v[0]} and #{v[1]} follow #{v[2]}"}
# ["John and James follow Jakob", "Janette and Jean follow Juilia"]
array.select{|v|v[/^J[a-z]+/]}.each_slice(3).map{|v| "#{v[0]} and #{v[1]} follow #{v[2]}"}.
join("\n") 
# "John and James follow Jakob\nJanette and Jean follow Juilia"

Использовать только стандартную библиотеку.

Целесообразность операции не важна. Вопрос кратности количества найденных элементов трем не рассматриваем.



Последнее исправление: ymn (всего исправлений: 3)

Для тех кто ничо не понял, напиши человеческим языком, что ты хочешь сделать с последовательностью.

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

Из списка имен пассажиров выбрать тех, у кого имя начинается на J. Объединить их в группы по трое и получить текст, каждая строка которого описывает кто за кем едет в тройке.

На входе:

["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]

На выходе:

John and James follow Jakob
Janette and Jean follow Juilia

dr_jumba
() автор топика
array = ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]
filtered = [a for a in array if a[0] == "J"]
sliced = [filtered[i:i+3] for i in xrange(0, len(filtered), 3)]
string = "\n".join(["%s and %s follow %s" % (a, b, c) for a, b, c in sliced])
PolarFox ★★★★★
()
Ответ на: комментарий от dr_jumba
array = ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]
print "\n".join(["%s and %s follow %s" % (a, b, c) for a, b, c in [[a for a in array if a[0] == "J"][i:i+3] for i in xrange(0, len([a for a in array if a[0] == "J"]), 3)]])

Да пожалуйста. Только нормальные люди так не пишут.

PolarFox ★★★★★
()
Ответ на: комментарий от dr_jumba
(format nil "~:{~a and ~a follow ~a~%~}"
	(group (remove-if-not
		(lambda (x) (eql (elt x 0) #\J))
		'("John" "James" "Jakob" "Peter" "Janette" "Tom" "Vasya" "Jean" "Juilia" "Heather"))
	       3))

Можно использовать регексп с каррированием, лямбда с eql elt уберутся.

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

Де-факто это стандартная функция, каждый лиспер ее знает и пользует. Хотя, если цель встролльнуть... Не буду мешать.

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

Впрочем, держи без нее

(format nil "~{~a and ~a follow ~a~^~%~}"
	(remove-if-not
	 (lambda (x) (eql (elt x 0) #\J))
	 '("John" "James" "Jakob" "Peter" "Janette" "Tom" "Vasya" "Jean" "Juilia" "Heather")))

udp. Даже без переноса строки после последней строчки.

staseg ★★★★★
()
Последнее исправление: staseg (всего исправлений: 1)

Второй раз в жизни пейшу на кложуре:

(interpose "\n" 
           (map (partial apply (partial format "%s and %s follow %s"))
                (partition-all 3 (filter 
                                  #(re-matches #"J[a-z]+" %)
                                  ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]))))
zz ★★★★
()
Ответ на: комментарий от dr_jumba

Запускаю clisp и sbcl и не вижу в базовой поставке group.

Ну так она у всех есть в «своей» стандартной библиотеке :)

И да, выше уже ответил чотка по стандарту.

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

запускаю руби и не вижу в базовой поставке рельсов...

Пичалька. Стартовый пример работает без рельсовых гемов на чистом руби.

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

Пичалька. Стартовый пример работает без рельсовых гемов на чистом руби.

Т.е. ты решил померятся стандартной библиотекой. :)

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

Там надо (apply str добавить перед всем, но код куда это попадет и так наверняка сможет осилить список.

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

Не годится. Давай строку на выходе :) Будем считать, что я не могу осилить на clojure получить строку из списка.

dr_jumba
() автор топика

Питон

from itertools import zip_longest
import re

data = ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]

"\n".join(
    map(lambda x: "{} and {} follows".format(*x),
        zip_longest(*[iter(filter(lambda x: re.match("J[a-z]+", x), data))]*3)))
zz ★★★★
()
Ответ на: комментарий от PolarFox

выглядит примерно также

нет)) В руби это всего-навсего последовательный вызов четырех методов, суть

a.b.c.d
Но мне понравился твой однострочник, мужик)

special-k ★★★
()

Автор хочет в очередной раз затеять спор, какой язык лучше? Ответ: никакой. Каждый язык идеален в своей экологической нише.

Deleted
()

быстро и ужасно компактно:

string s; int n=0;
vector<string> l = { "John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather" };
for( auto i : l ) s+=i[0]=='J'?(n++?n%3==2?" and ":n%3?"\n":" follow ":"") + i:"";
wota ★★
()
Ответ на: комментарий от dr_jumba

Плохо знаю haskell, но вот например.

import Text.Regex.Posix
import Data.List.Split

main = do
  putStrLn
    $ unlines
    $ map (
      \arr -> arr !! 0 ++ " and " ++ arr !! 1 ++  " follow " ++ arr !! 2
      )
    $ chunk 3
    $ filter  (=~ "J") ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]
По сабжу, идея глупейшая, всё упирается в библиотеку - ничего интересного. на ЛОРе проводился конкурс по сравнению языков, надо было написать небольшое клиент-северное приложение. Поищи.

anonymous
()

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

trashymichael ★★★
()
Ответ на: комментарий от special-k

Но мне понравился твой однострочник, мужик)

Его было легко сделать, я просто подставил значения переменных.

PolarFox ★★★★★
()
Ответ на: комментарий от dr_jumba
try:
    from itertools import zip_longest
except ImportError:
    from itertools import izip_longest as zip_longest
import re

data = ["John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"]

print("\n".join(
    map(lambda x: "{} and {} follows".format(*x),
        zip_longest(*[iter(filter(lambda x: re.match("J[a-z]+", x), data))]*3))))

Для обоих веток.

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

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

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

Давай полную compile ready версию с include и namespaces.

#include <string>
#include <vector>
using namespace std;

int main() {
    string s; int n=0;
    vector<string> v = {"John", "James", "Jakob", "Peter", "Janette", "Tom", "Vasya", "Jean", "Juilia", "Heather"};
    for( auto i : v ) s+=i[0]=='J'?(n++?n%3==2?" and ":n%3?"\n":" follow ":"") + i:"";
}

жалста

wota ★★
()

Tcl

set L [list John James Jakob Peter Janette Tom Vasya Jean Juilia Heather]
puts [join [lmap {a b c} [lsearch -inline -all -regexp $L {^J[a-z]+}] {
    expr {"$a and $b follow $c"}
}] "\n"]
geekless ★★
()
Ответ на: комментарий от anonymous

Можно было и короче записать, но лень, когда можно убивать котят через $ (или ".").

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

На плюсах писал много лет назад. С какими ключами gcc/g++ это собирать? Ругается на инициализацию вектора.

dr_jumba
() автор топика
Ответ на: Tcl от geekless

Чёт на этом примере питон даже тикле сливает по читабельности. :-D

geekless ★★
()

haskell

import Data.List

meh = unlines . packem . filter ("J" `isPrefixOf`)
    where packem (x:y:z:rs) = (x ++ " and " ++ y ++ " follow " ++ z):packem rs
          packem  _ = []
Waterlaz ★★★★★
()
Последнее исправление: Waterlaz (всего исправлений: 2)
Ответ на: комментарий от special-k

Не так сильно как тут. Там больше кода, больше места равернуться.

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

map (
\arr -> arr !! 0 ++ " and " ++ arr !! 1 ++ " follow " ++ arr !! 2
)

можно так

map (\[x,y,z] -> x ++ " and " ++ y ++  " follow " ++ z)

или так

map (\[x,y,z] -> concat [x, " and ", y, " follow ", z])
Но всё равно затупит, когда число элементов не будет кратно 3.

Если regexp не является условием, то можно юзать isPrefixOf.

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

Спасибо, понял, что залажал просто списав пример после прочтения предыдущего поста с пингвином. Вечно забываю про матчинг.

anonymous
()
Ответ на: Tcl от geekless
set input [list "John" "James" "Jakob" "Peter" "Janette" "Tom"  "Vasya"  "Jean" "Juilia" "Heather"]
foreach {n1 n2 n3} [regexp -all -inline {\mJ[a-z]+\M} $input] {puts "$n1 and $n2 folow $n3"}
anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.