?

Log in

Сводный псто. - Жить не можем без проблем! [entries|archive|friends|userinfo]
Жить не можем без проблем!

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Сводный псто. [Dec. 7th, 2010|11:30 am]
Жить не можем без проблем!

ru_lisp

[jamhed]
В помощь выбирающему языг:

задан список файлов в командной строке, надо вывести последовательно
1-ю строку из 1-го файла
1-ю строку из 2-го файла
1-ю строку из 3-го файла
...
1-ю строку из N-го файла
2-ю строку из 1-го файла
2-ю строку из 2-го файла
2-ю строку из 3-го файла
...
2-ю строку из N-го файла

ну и так далее, причем количество строк в файлах разное



Haskell:
import System
import Data.List
main = getArgs >>= mapM readFile >>= mapM_ putStrLn . concat . transpose . map (lines)


Perl:
my @fs = map { open(my $fh, $_); $fh } @ARGV;
while( my @fh = grep { not eof($_) } @fs ) { print my $f = readline($_) foreach (@fh) };


Ruby:
fs = ARGV.map { |fn| File.open(fn) }
while fs.map(&:eof?).include? false
   fs.each { |f| puts f.gets unless f.eof? }
end


LISP
(let ((files (mapcar #'open *args*)))                                                
  (loop                                               
    (unless (mapcan (lambda (f &aux (x (read-line f nil)))
                         (when x
                            (format t "~A~%" x) (list x)))
                    files)
	   (return))))


C++
#include 
#include 
#include 
#include 
#include 
using namespace std;

int __cdecl main(int argc, char *argv[]) {
	vector files(argc-1);
	for (int i=1; i<argc; ++i)
		files[i-1].open(argv[i]);
	for (bool hasLine=true; hasLine;) {
		hasLine = false;
		for (size_t i=0; i<files.size(); ++i) {
			string line;
			if (getline(files[i], line)) {
				hasLine = true;
				cout << line << endl;
			}
		}
	}
	return 0;
}


Erlang
компиляция erlc a.erl
запуск: erl -noshell -s a start -- file file1 file2 file3 

-module(a).
-export([start/0]).

start() ->
  output([ FD || {ok, FD} <- [ file:open(X, read) || X <- init:get_plain_arguments() ]]),
  erlang:halt().

output([]) -> ok;
output(List) ->
output(lists:filter(
fun(FD) ->
case io:get_line(FD, "") of
Line when is_list(Line) ->
io:format(Line), true;
_ -> false
end
end,
List
)
).


C#
static void Main(string[] args) {
	for (var files = args.Select(a => new StreamReader(a)).ToList(); 0 < files.Select(f => f.ReadLine()).Where(line => line != null).Count(line => { Console.WriteLine(line); 				return true; }); );
}


Java
package example.io;

import static net.sourceforge.jfunctions.functions.FunctionToolkit.*;
import static net.sourceforge.jfunctions.io.IOToolkit.file;
import static net.sourceforge.jfunctions.structures.StructureToolkit.list;
import net.sourceforge.jfunctions.io.FileLineParser;

public class SortLinesExample {
	
	public static void main(String[] args) {
		for (String line : merge(transform(transform(list(args), file()), FileLineParser.ignoringErrors()))) {
			System.out.println(line);
		}
	}
	
}


Python
import sys  
from itertools import izip_longest as izip, chain, ifilter

def main(args):
    for str in ifilter(lambda x: x is not None,
                       chain.from_iterable( izip( *[open(a) for a in args)] ) ):
        print str.rstrip()

if __name__=='__main__':
    main(sys.argv[1:])   


OCaml
open ExtLib
open List
let (>>) f g x = g (f x)
let (|>) x f = f x;;

let fs = Array.to_list Sys.argv |> tl |> map (open_in >> Std.input_lines) in
while fold_left (fun go e -> Option.may print_endline (Enum.get e); go || not (Enum.is_empty e)) false fs do () done


linkReply

Comments:
[User Picture]From: lispnik
2010-12-07 06:35 am (UTC)
lj-cut добавьте.
(Reply) (Thread)
[User Picture]From: freiksenet
2010-12-07 07:00 am (UTC)
Не LISP, а Lisp.

LISP - древние лиспы из 60-х.
lisp - общее название всех лиспов.
Lisp - Common Lisp.
(Reply) (Thread)
From: ander-skirnir.blogspot.com
2010-12-07 08:47 am (UTC)
Поддерживаю, еще предлагаю такой вариант:
(apply #'mapc #'(lambda (&rest ls)
                  (format t "~{~&~a~}" ls))
       (iter (for file :in *args*)
             (collect (iter (for line :in-file file
                                      :using #'read-line)
                            (collect line)))))
(Reply) (Parent) (Thread)
[User Picture]From: swizard
2010-12-07 01:10 pm (UTC)
Не очень вариант, оно в память содержимое сосет. Это же не хаскель с lazy io -- на громадных файлах все развалится.
(Reply) (Parent) (Thread)
[User Picture]From: migmit
2010-12-07 02:16 pm (UTC)
С Lazy I/O всё развалится раньше.
(Reply) (Parent) (Thread)
From: ander-skirnir.blogspot.com
2010-12-07 02:44 pm (UTC)
А можно коротко ликбез почему? :)
(Reply) (Parent) (Thread)
[User Picture]From: migmit
2010-12-07 04:33 pm (UTC)
do
   str <- hGetContents h
   ...
   doSomethingWith h
   ...

К моменту выполнения doSomethingWith - хэндл h уже закрыт или ещё нет? А фиг знает. Depends. Что там намудрил оптимизатор, была ли к этому моменту строка str обработана до конца...

По-нормальному в монаде IO последовательность действий строгая и ясная. Если подключается lazy i/o - последовательность действий летит в трубу.
(Reply) (Parent) (Thread)
From: ander-skirnir.blogspot.com
2010-12-07 06:01 pm (UTC)
Спасибо, понятно.
(Reply) (Parent) (Thread)
From: ander-skirnir.blogspot.com
2010-12-07 02:29 pm (UTC)
Ну тогда как дед завещал :)
(prog (f l (ss (mapcar #'open *args*)))
 s (dolist (s ss)
     (setq l (read-line s ()))
     (when l (setq f t)
           (format t "~&~a" l)))
   (unless f (return))
   (setq f ())
   (go s))
(Reply) (Parent) (Thread)
[User Picture]From: migmit
2010-12-07 08:39 am (UTC)
Решение на Haskell багнутое. В таком виде всё будет работать, но если писать хоть что-нибудь более крупное, lazy I/O стоит избегать по мере возможности.

Более правильный подход - со строгим I/O - выглядит примерно так:
doWhileM action = dwa where dwa = action >>= \b -> when b dwa
writeFirstLine h = hIsEOF h >>= \b -> if b then return False else hGetLine h >>= putStrLn >> return True
main = getArgs >>= \names -> mapM (ContT . flip withFile ReadMode) names `runContT` (doWhileM . liftM or . mapM writeFirstLine)
(Reply) (Thread)
[User Picture]From: Sergey Yelin
2010-12-07 10:38 am (UTC)
Для erlang можно чуть проще:

#!/usr/bin/escript

%% -*- erlang -*-

main(Args) ->
output([ FD || {ok, FD} <- [ file:open(X, read) || X <- Args]]),
erlang:halt().

output([]) -> ok;
output(List) ->
output(lists:filter(
fun(FD) ->
case file:read_line(FD) of
{ok, Line} -> io:format(Line), true;
_ -> false
end
end,
List)
).
(Reply) (Thread)
[User Picture]From: red1ynx
2010-12-07 12:14 pm (UTC)
Как-то не прикольно в Java подключаются нестандартные пакеты.
Так можно почти на любом языке в одну строчку сделать.
(Reply) (Thread)
[User Picture]From: jamhed
2010-12-07 12:16 pm (UTC)
Ну что было то было :)
(Reply) (Parent) (Thread)
From: wakes_up
2010-12-07 12:53 pm (UTC)
Bash как-то так:
for LINO in {1..5}; do echo {1..5}.txt | xargs -n 1 cat | head -n $LINO | tail -1; done
(Reply) (Thread)
From: sgrb.ya.ru
2010-12-07 02:29 pm (UTC)
Ну на лиспе мне сходу придумалось ещё два варианта не хуже предложенного:
1. через loop - ИМХО наиболее понятный:
(let ((files (mapcar #'open *args*)))
           (loop while (plusp (loop for f in files
                                 for line = (read-line f nil)
                                 count line
                                 when line
                                 do (format t "~a~%" line)))))
2. Рекурсивный:
(labels ((print-one (files)
                    (when files
                      (print-one (remove-if-not (lambda (f &aux (line  (read-line f nil)))
                                                  (when line
                                                    (format t "~a~%" line)
                                                    t))
                                                files)))))
           (print-one (mapcar #'open *args*)))
(Reply) (Thread)
[User Picture]From: love5an
2010-12-07 03:23 pm (UTC)
А можно объяснить, зачем конкретно такую задачу придется когда-нибудь решать?
Для "выбирающего язык" резонно было бы что-нибудь более жизненное привести в пример.

А для такой задачи, и подобных - perl, без вариантов.
(Reply) (Thread)
From: (Anonymous)
2010-12-07 10:27 pm (UTC)

newlisp script

Хмм..
Совсем не уверен, что я сделал это минимально/оптимально, но вот вам еще один вариант на скриптовом языке newlisp

    #!/usr/bin/newlisp
    
    ; this creates a list of filehandles
    (dolist (x (2 (main-args))) 
        (and (file? x) (push (open x "read") fhandles) )  ) 
    
    ; this iterates, prints and closes files as appropriate
    (while 
        (map (fn (x) 
            (if (set 'curr_line (read-line x)) 
                (println curr_line ) 
                (close (pop fhandles $idx)) )) 
            fhandles ) )
    (exit)
    


Я не старался написать всё в одну строчку, разбил как понятнее
(Reply) (Thread)
From: (Anonymous)
2010-12-12 08:13 am (UTC)

D

на Digital Mars D:

import std.stdio;
import std.algorithm;

void main(string[] args)
{
File[] files;
foreach(x;args[1..$])files~=File(x);
while(count!("!a.eof()")(files) > 0)
{
foreach(i,f;files)writef(" %s:%s ",i,f.readln());
writeln();
}
}

Как оказалось, map в std.algorithm вызывет деструктор для обьектов, созданных внутри его тела. Оно и понятно - при выходе покидается scope, где они были созданы.
(Reply) (Thread)