join di due files

Ho due files cosi fatti

file 1
x y z1 z2 z3
1 2 11 12 13
3 4 14 15 16
5 6 17 18 19
7 8 20 21 22

file 2
x y k1 k2 k3
3 4 31 32 33
7 8 34 35 36
5 6 37 38 39
1 2 40 41 42

Quello che vorrei ottenere e’

x y z1 z2 z3 k1 k2 k3
1 2 11 12 13 40 41 42
3 4 14 15 16 31 32 33
5 6 17 18 19 37 38 39
7 8 20 21 22 34 35 36

uso join dopo un sort? Cosa combina se per caso x e y non corrispondono? posso fare il join su tutte e due (x,y) le colonne?

awk potrebbe essere un’alternativa? non ho trovato molto di funzionante sull’amico google :wall:

Grazie!

Hai dato un’occhiata ai “man …”?

Ciao

Secondo me per questo genere di compiti è molto meglio rivolgersi a Perl o Python.

Ciao Ciao, Moreno

dato un’occhiata ai man … e poi fatto domande per essere sicura.

Penso che python sara’ la strada a questo punto. Anche se ho paura che ci mettera’ una vita data la quantita’ di righe su cui fare il loop.
Pensavo che awk (se mai capiro’ come fare) potesse essere piu’ veloce.

Grazie!

Ciao

Se ho ben capito tu dovresti fare una cosa del genere:

for (i1 = 0 ; i1 < T1.length ; i1++)
 for (i2 = 0 ; i2 < T2.length ; i2++)
  if ( (T1[i1].X == T2[i2].X) AND
       (T1[i1].Y == T2[i2].Y)
   {
    Aggiungo elementi di T2 a T1;
    Elimino riga di T2 già assegnata;
    i2--;
    break;
   }

Esatto??
Penso che non ci possa essere nessun algoritmo più veloce.
Bisogna vedere se è conveniente eliminare la riga già usata o semplicemente marcarla come già usata assegnando valori impossibili a X ed Y.

Ciao Ciao, Moreno

Morenoooo… mai dire mai…

L’ algoritmo che hai postato su non è molto efficiente, effettua troppi cicli, si può risolvere in python in modo linerare così:

Crei un dizionario che ha come chiave “x-y” (es. 3-4 ),
scorri il file 1 dalla testa alla coda,e inserisci le chiavi e una lista con i 3 elementi. Poi scorri il secondo file, riprendi tramite dizionario (praticamente è una hashtable) la lista dei 3 numeri e gli accodi gli altri 3.

Alla fine hai una hashtable che puoi anche ordinare con tutti i valori dei due file.
Ciao.

Ciao

Se ho ben capito vorresti usare x,y come puntatore ad una tabella che riempi con i valori.

Sì a parte l’occupazione di memoria effettivamente la cosa sta in piedi a patto che x ed y siano interi

Quindi verrebbe fuori più o meno:

/* MT = MAX_X*MAX_Y*2*NUM_PARM */
for (i1 = 0 ; i1 < T1.length ; i1++)
 MT[T1[i1].x1][T1[i1].y1][0].Valori = T1.Valori;

for (i2 = 0 ; i2 < T2.length ; i2++)
 MT[T2[i2].x2][T2[i2].y2][1].Valori = T1.Valori;


/* MF = (T1.length + T2.length)*((2*NUM_PARM)+2)*/
int Rec = 0;
for (i1 = 0 ; i1 < T1.length ; i1++)
 {
  MF[Rec][0].Valori = MT[T1[i1].x1][T1[i1].y1][0].Valori;
  MF[Rec][1].Valori = MT[T1[i1].x1][T1[i1].y1][1].Valori;
  MT[T1[i1].x1][T1[i1].y1].Usato = 1;
  Rec++
 }
for (i2 = 0 ; i2 < T2.length ; i2++)
 if (MT[T2[i2].x2][T2[i2].y2].Usato == 0)
  {
   MF[Rec][0].Valori = MT[T2[i2].x2][T2[i2].y2][0].Valori;
   MF[Rec][1].Valori = MT[T2[i2].x2][T2[i2].y2][1].Valori;
   Rec++
  }

Sort finale in base a X ed Y della tabella MF

Sì effettivamente così è più veloce.

Ciao Ciao, Moreno
*/

si, premesso che per sviluppare bene l’ algoritmo si devono conoscere bene i dati, e quello che è stato postato è poco.

Comunque fatto come l’ hai fatto tu in C richiede molta memoria e indici interi, se invece usi python e i dizionari allochi solo quello che ti serve e gli indici possono essere come ti pare.

Se poi si vuole la velocità allora basta unire il C ad una struttura hash e così stai a posto.
Python per queste cose è imbattibile e non è nemmeno tanto lento, certo se ti serve il realtime è un’altra cosa, ma in passato ho fatto programmi di calcolo abbastanza pesanti e il python se la cavav egregiamente.

Ciao.

Ciao

Ah ora ho capito cosa intendevi, liste di oggetti ordinati, una roda del tipo

for (i1 = 0 ; i1 < T1.length ; i1++)
 {
  if (Esiste (T1[i1].x1,T1[i1].y1) == false)
   Aggiungi (T1[i1].x1,T1[i1].y1)
  Parametri(T1[i1].x1,T1[i1].y1,0,T1.Valori);
 }
for (i2 = 0 ; i2 < T2.length ; i2++)
 {
  if (Esiste (T2[i2].x2,T2[i2].y2) == false)
   Aggiungi (T2[i2].x2,T2[i2].y2)
  Parametri(T2[i2].x2,T2[i2].y2,1,T2.Valori);
 }

Comunque avendo a disposizione memoria illimitata il mio precedente algoritmo è sicuramente più veloce.

Ciao Ciao, Moreno

Grazie a entrambi per le idee. Ho appena finito un corso di python, sicuramente domani ci provo a farmi lo script!

Non ho il file dei dati con me quindi non posso giocarci questasera. Comunque x e y sono coordinate in metri. Le altre colonne sono dati vari, per la maggior parte integer.

Domani posto eventuali progressi o piu probabilmente … dubbi!

Grazie!

allora, te lo faccio in simil-python ( simil perché la sintassi non sarà perfetta, vado a memoria…)

mainDiz={}   // Dizionario

file1=open(file1_name)
file2=open(file2_name)

while file1.eof:
  riga1=leggi_riga_e_return_lista_parametri()  // funzione che legge la riga e ritorna un'array di parametri

 lista1=[riga1[2],riga1[3],riga1[4]]

 mainDiz""+riga1[0]+""+riga[1]]=lista1  // inserisco i valori nel dizionario
    
end while


while file2.eof:
  riga2=leggi_riga_e_return_lista_parametri()  // funzione che legge la riga e ritorna un'array di parametri

 lista2=[riga2[2],riga2[3],riga2[4]]
 lista1=mainDiz""+riga2[0]+""+riga2[1]]  //estraggo i primi tre valori dal dizionario
 
 mainDiz""+riga2[0]+""+riga2[1]]=lista1+lista2  // aggiungo gli ultimi 3 valori
    
end while

ovviamente è sintetizzato l’ algoritmo, mancano tutti i try /catch e deve essere tradotto sintaticamente in python.

io ho fatto questo che dal mio punto di vista non è proprio elegante,ma lo ho fatto perche volevo participare a questo bell topic :slight_smile:

#!/bin/bash

IFS=$’\n’

BIG=(“x y k1 k2 k3” “3 4 31 32 33” “7 8 34 35 362” “5 6 37 38 39” “1 2 40 41 42”)

typeset -i NUM=0

for i in $(<1.txt)
do
var=$((NUM++))
ARRY$var]=$i
echo “$i” ${BIG$var]}
done

ahahah azz… questo è BARARE!!! :slight_smile:

jajajaja dai che non lo ho fatto a posta.volevo solo essere presente a questo topic :slight_smile:

chiedo scusa se ho barato,comunque ho modificato la robba che ho fatto che a me non piace se a qualcuno li piace me lo dica cosi me tira sul il morale :frowning:

#!/bin/bash

IFS=$’\n’

BIG=(while read uno;do echo "$uno";done < 2.txt)

typeset -i NUM=0

for i in $(<1.txt)
do

ARRY$var]=$i

echo “$i” ${BIG$var]} | sed ‘s/"//g’
var=$((NUM++))
done

ari grazie a tutti quanti! mi sto studiando il simil script.
Da quello che ho capito dei dizionari dovrebbe funzionare anche su dati non ordinati … o ho bisogno di andare a dormire ?

i dizionari poi te li ordini come vuoi, i dati iniziali possono essere come pare a te.

Notte

Sono riuscita a fare meno del previsto quindi ho rotto meno del previsto!

Sono riuscita a leggere i files come dizionari sia per righe che per colonne:

import csv

file1=open('file.csv', 'rb')
rfile1=csv.reader(file1, delimiter='\t')

header1=rfile1.next()

data_dict1={}
for head in header1:
  data_dict1[head]=]

for row in rfile1:
  for index, head in enumerate(header1):
    data_dict1[head].append(row[index])
file1=open('file.csv', 'rb')
rdfile1=csv.DictReader(file1, delimiter='\t')

Sono riuscita a fare eventualmente un check sulle chiavi, cioe’ controllare che le chiavi corrispondano.

Non sono ancora riuscita a copiare i dati del secondo file nel primo.
Ma la domanda a questo punto e’: piu’ semplice leggere i dati per colonna o per riga?

Grazie :hammer:

[quote=marmtt]

Sono riuscita a fare eventualmente un check sulle chiavi, cioe’ controllare che le chiavi corrispondano.

Non sono ancora riuscita a copiare i dati del secondo file nel primo.
Ma la domanda a questo punto e’: piu’ semplice leggere i dati per colonna o per riga?

Grazie :hammer:[/quote]

per riga … così:

file = open("sample.txt")

while 1:
    line = file.readline()
    if not line:
        break
    primoInsieme=line.split('\t')

#adesso primo insieme contiene una lista con i numeri nella riga, quindi primoInsieme[0] sarà x e così via..
#QUindi metti i tre numeri dentro il dizionario con la giusta chiave:
    mainDict[primoInsieme[0]+'-'+primoInsieme[1]]=[primoInsieme[2],primoInsieme[3],primoInsieme[4]]

.....
......
poi fai un altro while con l' altro file , riprendi la lista dal dizionario e gli accodi ( mi pare con append) gli altri 3 numeri . capito?

lascia stare questo codice, è tutto sbagliato, guardati bene il simil-python, è molto semplice.

te lo rispiego in altro modo:

  1. apro il file e prendo una riga
  2. splitto la riga e creo una lista con i numeri della riga, quindi riga[0] sarà x, riga[1] sarà y ecc…e.cc…
  3. inserisco gli ultimi 3 valori della lista in un dizionario che ha per chiave “x-y” , quindi riga[0]+"-"riga[1]
  4. passo all’ altra riga … fino alla fine del file.

a questo punto ho un dizionario che contiene tutto il mio primo file, ha come chiavi “x-y” e a ogni coppia ha associata la lista di tre numeri corrispondente, quindi:

  1. Apri il secondo file e prendi una riga
  2. recupera dal dizionario la lista che ha per chiave “x-y” appena letti dal 2° file
  3. aggiungi alla lista recuperata dal dizionario i tre numeri letti dal 2° file
  4. continua per tutte le altre righe del 2° file

Alla fine ottieni un dizionario che ha per chiavi “x-y” a cui sono associati i sei numeri corrispondenti

Così è più chiaro?

Grazie per il supporto! L’ho capito :hammer: alla buona ora!
Mi stavo complicando la vita in un modo assurdo.

Adesso devo pensare a come risolverlo per un numero di colonne molto maggiore e non uguale per tutti i files!