2013-01-23 19 views
6

Ho un gruppo di stringhe che contengono elenchi di nomi nel formato , nome, separati da virgole, in questo modo:"cognome, nome" -> "nome cognome" in stringhe serializzate

names <- c('Beaufoy, Simon, Boyle, Danny','Nolan, Christopher','Blumberg, Stuart, Cholodenko, Lisa','Seidler, David','Sorkin, Aaron') 

Qual è il modo più semplice per convertire tutti questi nomi all'interno delle stringhe per nome cognome formato?

+0

Ci saranno sempre coppie di nomi o ci saranno persone con più di due soli nomi? – A5C1D2H2I1M1N2O1R2T1

+0

Intendi qualcosa come "Hoover, J. Edgar"? Potrebbe essere. È davvero spiacevole che lo stesso separatore sia stato utilizzato per separare l'ultimo dal nome e dai nomi degli altri sami. Ma è così, ho paura. Ciò che è vero (spero ...) è che le virgole non compaiono all'interno di un nome o di un cognome. – RoyalTS

+0

Penso che il suo esempio avesse alcune citazioni mancanti. Se un singolo elemento contiene più di un nome allora probabilmente ci sarebbe molto lavoro (spaccare e ricombinare per formare un nome univoco e così via) prima di poter fare una semplice regex. –

risposta

9

Se si può essere certi che una virgola non sta per essere in nome di una persona, questo potrebbe funzionare:

mynames <- c('Beaufoy, Simon, Boyle, Danny', 
      'Nolan, Christopher', 
      'Blumberg, Stuart, Cholodenko, Lisa', 
      'Seidler, David', 
      'Sorkin, Aaron', 
      'Hoover, J. Edgar') 
mynames2 <- strsplit(mynames, ", ") 

unlist(lapply(mynames2, 
       function(x) paste(x[1:length(x) %% 2 == 0], 
           x[1:length(x) %% 2 != 0]))) 
# [1] "Simon Beaufoy"  "Danny Boyle"  "Christopher Nolan" 
# [4] "Stuart Blumberg" "Lisa Cholodenko" "David Seidler"  
# [7] "Aaron Sorkin"  "J. Edgar Hoover"   

Ho aggiunto J. Edgar Hoover in là per buona misura.

Se si desidera che i nomi che sono stati citati insieme per stare insieme, aggiungere collapse = ", " al vostro paste() funzione:

unlist(lapply(mynames2, 
       function(x) paste(x[1:length(x) %% 2 == 0], 
           x[1:length(x) %% 2 != 0], 
           collapse = ", "))) 
# [1] "Simon Beaufoy, Danny Boyle"  "Christopher Nolan"    
# [3] "Stuart Blumberg, Lisa Cholodenko" "David Seidler"     
# [5] "Aaron Sorkin"      "J. Edgar Hoover"  
+0

Bello, grazie!Un modo per rimettere insieme le stringhe alla fine? – RoyalTS

+0

@RoyalTS, aggiunto un aggiornamento. – A5C1D2H2I1M1N2O1R2T1

+0

Perfetto! Grazie mille. – RoyalTS

1

Sono a favore della @ di AnandaMahto risposta, ma solo per divertimento, questo illustra un altro metodo utilizzando scan, split e rapply.

names <- c(names, 'Chambers, John, Ihaka, Ross, Gentleman, Robert') 

# extract names 
snames <- 
lapply(names, function(x) scan(text=x, what='', sep=',', strip.white=TRUE, quiet=TRUE)) 

# break up names 
snames<-lapply(snames, function(x) split(x, rep(seq(length(x) %/% 2), each=2))) 

# collapse together, reversed 
rapply(snames, function(x) paste(x[2:1], collapse=' ')) 
3

(1) Mantenere stessi nomi in ciascun elemento Questo può essere fatto con un singolo gsub (assumendo non ci sono virgole all'interno dei nomi):

> gsub("([^, ][^,]*), ([^,]+)", "\\2 \\1", names) 
[1] "Simon Beaufoy, Danny Boyle"  "Christopher Nolan"    
[3] "Stuart Blumberg, Lisa Cholodenko" "David Seidler"     
[5] "Aaron Sorkin"  

> gsub("([^, ][^,]*), ([^,]+)", "\\2 \\1", "Hoover, J. Edgar") 
[1] "J. Edgar Hoover" 

(2) separati in un unico nome per elemento Se si desidera il cognome di ciascun nome in un elemento separato, utilizzare (a) scansione

scan(text = out, sep = ",", what = "") 

dove out è il risultato della gsub sopra o per farlo provare direttamente (b) strapply:

> library(gsubfn) 
> strapply(names, "([^, ][^,]*), ([^,]+)", x + y ~ paste(y, x), simplify = c) 
[1] "Simon Beaufoy"  "Danny Boyle"  "Christopher Nolan" 
[4] "Stuart Blumberg" "Lisa Cholodenko" "David Seidler"  
[7] "Aaron Sorkin"  

> strapply("Hoover, Edgar J.", "([^, ][^,]*), ([^,]+)", x + y ~ paste(y, x), 
+ simplify = c) 
[1] "Edgar J. Hoover" 

noti che tutti gli esempi sopra usato la stessa espressione regolare per la corrispondenza.

AGGIORNAMENTO: rimossa la virgola che separa il nome e il cognome.

AGGIORNAMENTO: codice aggiunto per separare il cognome di ciascun nome in un elemento separato nel caso in cui si tratti del formato di output preferito.

+0

Grazie per la spiegazione molto approfondita. Mi piacerebbe questo più, se potessi! – RoyalTS

+0

È davvero fantastico. Non mi è venuto in mente che la regex avrebbe funzionato in quel modo, quindi non mi sono preoccupato di provarlo! – A5C1D2H2I1M1N2O1R2T1

Problemi correlati