PDA

Visualizza la versione completa : [C/C++/BASH/PERL] Estrarre casualmente x righe da file


Ol3iconfini
20-05-2007, 13:45
Salve a tutti, come al solito ho una domanda da porre alla vostra attenzione:
dato un file1 di n righe (con n abbastanza grande, circa 2000), come posso estrarre x righe randomicamente (con x abbastanza piccolo, circa 200), per creare quindi un secondo file2?
Mi sembrava ridicolo scrivere un programma in c/c++ che estragga randomicamente x numeri tra 1 e 2000 e poi scrivere uno script in bash che stampa quelle x righe...
Qualcuno ha un metodo più elegante da proporre?

Forse posso utilizzare sed o awk in connessione con $RANDOM?
O magari esiste già qualche script in perl?

Grazie per le risposte.

Xaratroom
20-05-2007, 17:24
quindi in che linguaggio intendi farlo, partendo dal presupposto che ti daremo una mano ?

Ol3iconfini
20-05-2007, 18:29
Ho proposto vari linguaggi, dato che non ho una preferenza...
Pensavo che in bash o in perl si possano manipolare meglio i file...
Ma l' importante è il risultato e non il mezzo col quale lo ottengo.

Comunque in bash l' idea è quella di generare un numero casuale con $RANDOM e poi magari numerare le righe del file da cui estrarre le righe e prendere solo la riga numero $RANDOM...
In più dovrei controllare che la riga estratta non sia già stata estratta in precedenza...
Qualche aiuto?

Xaratroom
21-05-2007, 09:17
Premetto che quello che hai pensato di fare in bash si può fare (e lo devi fare cmq per risolvere il problema) con gli altri linguaggi (credo che il modo più semplice e anche "portabile" sia quello di usare c++ e perl, inoltre un compilato è più veloce)...
Cmq puoi prima calcolarti i valori random e metterli in un vettore e poi leggere le righe (in questo modo potrai controllare i valori precedentemente inseriti)...

Xaratroom
21-05-2007, 09:51
ti o fatto un abozzo in cpp:


void Genera (unsigned int v[], unsigned int x, unsigned int max)
{ /*genera x numeri casuali, inseriti in v con range da 0 a max*/
unsigned int i = 0;
srand ((unsigned int) time(NULL));
for (unsigned int i = 0; i < x; i++)
v[i] = rand()%max;

for (unsigned int i = 0; i < x; i++)
for (unsigned int j = 0; j < i; j++)
if (v[i] == v[j])
{
v[i] = rand()%max;
i = 0;
}
}

unsigned int ContaRighe (char *Path)
{ /*conta le righe presenti nel file*/
ifstream file (Path, ios::in);
if (file)
{
unsigned int i = 0;
char buffer [1000];
while (file>>buffer)
i++;
file.close();
return i;
}
return 0;
}

Ol3iconfini
21-05-2007, 12:29
Ti ringrazio, ho provato in bash con questo codice, ma non funge... :oVVoVe:
Qualche aiuto?



#!/bin/bash
# Verifica degli argomenti
ARG=2
E_ERR_ARG=65
if [ $# -ne "$ARG" ]
then
echo "Utilizzo: $0 file_da_leggere file_da_creare"
exit $E_ERR_ARG
fi
#

fileSorg=$1
fileDest=$2
numRighe=4 # 1986 righe
max=2 #264 numero di righe da leggere
contatore=1

let "casuale = (($RANDOM % $numRighe)+1)"

while [ "$contatore" -le $max ]
do
if [ "${vect[$casuale]}" -ne "$casuale" ]
then
head $fileSorg -n$casuale | tail -n1 >> $fileDest
vect[$casuale] = $casuale
let "casuale = (($RANDOM % $numRighe)+1)"
let "contatore += 1"
else
let "casuale = (($RANDOM % $numRighe)+1)"

fi
done

:dhò: :bhò:

Forse è meglio se si sposta il thread in linux, magari lì c'è qualcuno che ha più familiarità col bash?

billiejoex
21-05-2007, 13:05
In python:


import random

lines = []
fin = open('file.in', 'r')
fout = open('file.out', 'w')

for line in fin.readlines():
lines.append(line.strip())

while lines:
line_no = random.randint(0, len(lines))
fout.write (lines.pop(line_no - 1) + '\n')

Ol3iconfini
21-05-2007, 13:18
Originariamente inviato da billiejoex
In python:


import random

lines = []
fin = open('file.in', 'r')
fout = open('file.out', 'w')

for line in fin.readlines():
lines.append(line.strip())

while lines:
line_no = random.randint(0, len(lines))
fout.write (lines.pop(line_no - 1) + '\n')

Aspetta, mi sono perso...
Per estrarre 264 righe tra le 1986 basta quel codice??? :confused:

billiejoex
21-05-2007, 13:31
Ah allora no, ho capito male. Quello le estrae tutte e le ripone in un secondo file in maniera casuale. Se nel primo ne hai 2000 nel secondo ne avrai 2000. Per fare come dici tu dovrebbe bastare cambiare la linea del while da:


while lines:

...a:


while (len(lines) != 1986 - 264):

(non testato, fallo tu)

Ol3iconfini
21-05-2007, 14:42
Grazie mille, billiejoex! :unz:
Questo è il codice, e funziona:

#!/usr/bin/python
import random

lines = []
fin = open('source.txt', 'r')
fout = open('dest.txt', 'w')

for line in fin.readlines():
lines.append(line.strip())

while (len(lines) != 1986 - 264):
line_no = random.randint(0, len(lines))
fout.write (lines.pop(line_no - 1) + '\n')

Ma le righe estratte sono tutte diverse o c' è la possibilità di doppioni? Perché a me servono linee distinte tra loro...

Puoi spiegarmi il significato di:
while (len(lines) != 1986 - 264):
??

Grazie ancora billi! :ciauz:

Loading