Concatena più voci di elenco insiemeUtilizzo di JMP12.2: sto cercando un modo rapido per concatenare gli elementi dell'elenco da due elenchi diversi in modo 1 a 1, supponendo che gli elenchi abbiano lo stesso numero di elementi. Questo verrà utilizzato per ogni riga in tabelle molto grandi, quindi preferisco nessuna funzione iterativa, se possibile.
Ecco un esempio di quello che voglio ottenere:
lista1 = {"a","b","c","d","e","f","g"};
lista2 = {"1","2","3","4","5","6","7"};
Il risultato accettabile può essere una stringa o un elenco. Se stringa separata da delimitatori.
Risultato elenco: {"a,1","b,2","c,3","d,4","e,5","f,6","g,7"};
Risultato stringa: "a:1,b:2,c:3,d:4,e:5,f:6,g:7";
Personalizzazione di massaRi: Concatenare più voci di elenco insiemeHo fatto un casino! Ecco una versione aggiornata che probabilmente funzionerà correttamente nelle versioni precedenti di JMP:
dtGraph = New Table( "stats",
Add Rows( 0 ),
New Column( "size", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [] ) ),
New Column( "table time", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [] ) ),
New Column( "loop time", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [] ) )
);
For( n = 1, n < 1e7, n *= 2,
dtGraph << addrows( 1 );
dtGraph:size[N Rows( dtGraph )] = n * 3;// 3 items repeated...
list1 = Repeat( {"a", "b", "c"}, n );
list2 = Repeat( {"1", "2", "3"}, n );
start = HP Time(); // data table method begins here
dt = New Table( "temp",
New Column( "a", Character, "Nominal", Set Values( list1 ) ),
New Column( "b", Character, "Nominal", Set Values( list2 ) ),
New Column( "c", Character, "Nominal", formula( a || ":" || b ) ),
invisible
);
dt << runformulas;
result = dt:c << getvalues;
Close( dt, nosave );
stop = HP Time(); // data table method ends here
Show( stop - start );
result = Concat Items( result, "," );
Show( Length( result ), Left( result, 100 ) );
dtGraph:table time[N Rows( dtGraph )] = (stop - start) / 1e6;
result = {};
start = HP Time(); // loop method begins here
While(
aa = Remove From( list1, 1 );
bb = Remove From( list2, 1 );
N Items( aa ); // as long as something was removed...
, // do this...
Insert Into( result, aa[1] || ":" || bb[1], 1 ) // <<<<<<<<< here
);
result=reverse(result); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< and here
stop = HP Time(); // loop method ends here
Show( stop - start );
result = Concat Items( result, "," );
Show( Length( result ), Left( result, 100 ) );
dtGraph:loop time[N Rows( dtGraph )] = (stop - start) / 1e6;
Wait( 1 );
);
dtGraph << Graph Builder(
Size( 1200, 500 ),
Show Control Panel( 0 ),
Variables( X( :size ), Y( :table time ), Y( :loop time, Position( 1 ) ) ),
Elements( Points( X, Y( 1 ), Y( 2 ), Legend( 5 ) ), Smoother( X, Y( 1 ), Y( 2 ), Legend( 6 ) ) ),
SendToReport(
Dispatch( {}, "size", ScaleBox, {Scale( "Log" ), Inc( 1 ), Minor Ticks( 1 )} ),
Dispatch( {}, "table time", ScaleBox, {Scale( "Log" ), Format( "Best", 12 ), Inc( 1 ), Minor Ticks( 1 )} )
)
);Vedere Elenco veloce per una spiegazione; Mi stavo concentrando sulla funzione RemoveFrom e dimenticando la funzione Insert Into.
Insert Into needs a 3rd argument to insert at the beginning of the list, and then a reverse when done.Insert Into needs a 3rd argument to insert at the beginning of the list, and then a reverse when done.Insert Into necessita di un terzo argomento da inserire all'inizio dell'elenco, quindi di un'operazione inversa al termine.
Ho anche rinominato le variabili nel ciclo in modo che non utilizzassero le colonne della tabella dati come temporanee.
Ri: Concatenare più voci di elenco insiemeIl mio problema è risolto: questo è più un FYI per te e per altri che potrebbero trovarlo utile.
Ho accesso a JMP14.3 ma lo script deve essere eseguito su JMP12.2 per la compatibilità all'interno della mia organizzazione.
Ho provato la tua analisi e per JMP14.3 ho ottenuto risultati simili ai tuoi, probabilmente alcune differenze nella potenza di calcolo.

Tuttavia, JMP12.2 le prestazioni del ciclo vanno completamente fuori linea. Devo terminare il processo JMP.exe dopo 98304 poiché il tempo aumentava in modo esponenziale e non avrebbe mai raggiunto la 24a riga:

Ri: Concatenare più voci di elenco insiemeGrazie questo funziona alla grande. Anche se utilizza una funzione iterativa ha buone prestazioni.
Ri: Concatenare più voci di elenco insiemeSì, potrei aver supposto che iterativo (per) all'interno di iterativo (per ogni riga) avrebbe avuto un grave impatto sulle prestazioni dello script, ma dopo aver creato l'esempio @SDF1 ha suggerito che la performance è sorprendentemente buona.
Grazie per il confronto: avrei pensato che il c++ sarebbe sempre stato più veloce, ma ha senso che un tavolo avrebbe sempre più sovraccarico. Mi chiedo se la tabella "Begin Data Update" e/o "Private" migliorerebbe il sovraccarico della tabella?
Ri: Concatenare più voci di elenco insiemeI loop JSL hanno una reputazione immeritatamente cattiva. Se le viscere del ciclo funzionano molto, l'overhead del ciclo di solito non ha molta importanza. E qualsiasi soluzione senza un ciclo JSL comporterà un ciclo da qualche altra parte, forse in C++ che sarà un po' più veloce, ma comunque. Ad ogni modo, ecco un confronto tra due metodi, uno che coinvolge un ciclo JSL e uno che utilizza un ciclo nascosto nel codice C++ di JMP.
Graph showing crossover times of the two algorithms at around 39,000 elements.Graph showing crossover times of the two algorithms at around 39,000 elements.Grafico che mostra i tempi di crossover dei due algoritmi a circa 39.000 elementi.
dtGraph = New Table( "stats",
Add Rows( 0 ),
New Column( "size", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [] ) ),
New Column( "table time", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [] ) ),
New Column( "loop time", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [] ) )
);
For( n = 1, n < 1e7, n *= 2,
dtGraph << addrows( 1 );
dtGraph:size[N Rows( dtGraph )] = n * 3;// 3 items repeated...
list1 = Repeat( {"a", "b", "c"}, n );
list2 = Repeat( {"1", "2", "3"}, n );
start = HP Time(); // data table method begins here
dt = New Table( "temp",
New Column( "a", Character, "Nominal", Set Values( list1 ) ),
New Column( "b", Character, "Nominal", Set Values( list2 ) ),
New Column( "c", Character, "Nominal", formula( a || ":" || b ) ),
invisible
);
dt << runformulas;
result = dt:c << getvalues;
Close( dt, nosave );
stop = HP Time(); // data table method ends here
Show( stop - start );
result = Concat Items( result, "," );
Show( Length( result ), Left( result, 100 ) );
dtGraph:table time[N Rows( dtGraph )] = (stop - start) / 1e6;
result = {};
start = HP Time(); // loop method begins here
While(
a = Remove From( list1, 1 );
b = Remove From( list2, 1 );
N Items( a ); // as long as something was removed...
, // do this...
Insert Into( result, a[1] || ":" || b[1] )
);
stop = HP Time(); // loop method ends here
Show( stop - start );
result = Concat Items( result, "," );
Show( Length( result ), Left( result, 100 ) );
dtGraph:loop time[N Rows( dtGraph )] = (stop - start) / 1e6;
Wait( 1 );
);
dtGraph << Graph Builder(
Size( 1200, 500 ),
Show Control Panel( 0 ),
Variables( X( :size ), Y( :table time ), Y( :loop time, Position( 1 ) ) ),
Elements( Points( X, Y( 1 ), Y( 2 ), Legend( 5 ) ), Smoother( X, Y( 1 ), Y( 2 ), Legend( 6 ) ) ),
SendToReport(
Dispatch( {}, "size", ScaleBox, {Scale( "Log" ), Inc( 1 ), Minor Ticks( 1 )} ),
Dispatch( {}, "table time", ScaleBox, {Scale( "Log" ), Format( "Best", 12 ), Inc( 1 ), Minor Ticks( 1 )} )
)
);JMP 14 è il più vecchio a cui ho accesso. Penso che l'algoritmo del ciclo avrà prestazioni simili in JMP 12. Distrugge intenzionalmente i due elenchi mentre li elabora perché le versioni precedenti di JMP non avevano un'indicizzazione rapida negli elenchi, ma la rimozione del primo elemento è rapida. L'algoritmo della tabella dati è il primo nel ciclo, quindi può utilizzare gli elenchi prima che vengano distrutti.
Guardando indietro al JSL, non dovrei affermare che nessuno degli algoritmi sia più semplice o più facile da seguire.
Ri: Concatenare più voci di elenco insiemeCIAO @ts2 ,
A seconda di cosa vuoi fare con i risultati, potresti affrontarlo in un paio di modi diversi. So che non vuoi fare funzioni iterative, ma per ottenere l'output giusto in cui gli elementi di una lista sono collegati agli elementi di un'altra lista, penso che devi fare un For Loop. Potresti anche considerare di creare un array associativo.
Di seguito sono riportati alcuni JSL che potrebbero aiutarti a iniziare una soluzione.
names default to here(1);
list1 = {"a","b","c","d","e","f","g"};
list2 = {"1","2","3","4","5","6","7"};
AA = Associative Array(List1, List2);
i=.;
result1={};
For(i=1, i<=nitems(list1), i++,
result1[i]=list1[i]||":"||list2[i]
);
result 2 = EvalList({Concat Items(result1, ", ")});
Show(result1);
Show(result2);
Show (AA);Spero che questo ti aiuti!,
DS