Preciso fazer uma divisão simples de uma string, mas não parece haver uma função para isso, e a maneira manual que testei não parecia funcionar. Como eu faria isso?
Aqui está minha solução realmente simples. Use a função gmatch para capturar cadeias que contenham pelo menos um caractere de outra coisa que não seja o separador desejado. O separador é ** qualquer * espaço em branco (% s em Lua) por padrão:
function mysplit (inputstr, sep)if sep ==nilthen
sep ="%s"endlocal t={}for str in string.gmatch(inputstr,"([^"..sep.."]+)")do
table.insert(t, str)endreturn t
end
Uau, a primeira resposta em toda essa pergunta que realmente tem uma função que retorna uma tabela. Note, no entanto, que eu preciso do modificador "local", pois você está substituindo os globais. :)
cib
3
Como outros já apontaram, você pode simplificar isso usando table.insert (t, str) em vez de t [i] = str e então você não precisa de i = 1 ou i = i +1
James Newton,
2
Não funciona se a string contiver valores vazios, por exemplo. 'foo,,bar'. Você obtém, em {'foo','bar'}vez de{'foo', '', 'bar'}
andras
5
Está certo. A próxima versão funcionará nesse caso: function split(inputstr, sep) sep=sep or '%s' local t={} for field,s in string.gmatch(inputstr, "([^"..sep.."]*)("..sep.."?)") do table.insert(t,field) if s=="" then return t end end end
bart
33
Se você estiver dividindo uma string em Lua, tente os métodos string.gmatch () ou string.sub (). Use o método string.sub () se você souber o índice no qual deseja dividir a string ou use o string.gmatch () se você analisará a string para encontrar o local em que ela será dividida.
O padrão %Sé igual ao que você mencionou, assim como %Sa negação de %s, assim como %Da negação de %d. Além disso, %wé igual a [A-Za-z0-9_](outros caracteres podem ser suportados dependendo do seu código do idioma).
Lars Gyrup Brink Nielsen
14
Assim como string.gmatchencontrará padrões em uma string, esta função encontrará as coisas entre os padrões:
function string:split(pat)
pat = pat or'%s+'local st, g =1, self:gmatch("()("..pat..")")localfunction getter(segs, seps, sep, cap1,...)
st = sep and seps +#sep
return self:sub(segs,(seps or0)-1), cap1 or sep,...endreturnfunction()if st thenreturn getter(st, g())endendend
Por padrão, ele retorna o que estiver separado por espaços em branco.
+1. Nota para qualquer outro iniciante do Lua: isso retorna um iterador e 'entre padrões' inclui o início e o fim da string. (Como um novato eu tinha que experimentar para descobrir isso.)
Darius Bacon
12
Aqui está a função:
function split(pString, pPattern)local Table ={}-- NOTE: use {n = 0} in Lua-5.0local fpat ="(.-)".. pPattern
local last_end =1local s, e, cap = pString:find(fpat,1)while s doif s ~=1or cap ~=""then
table.insert(Table,cap)end
last_end = e+1
s, e, cap = pString:find(fpat, last_end)endif last_end <=#pString then
cap = pString:sub(last_end)
table.insert(Table, cap)endreturn Table
end
Este é o meu favorito, pois é muito curto e simples. Eu não entendo direito o que acontece, alguém poderia me explicar?
Hexagonest
2
Esta falha ao usar ponto como delimitador (ou potencialmente qualquer outro personagem padrão de mágica)
TurboHz
6
Como há mais de uma maneira de esfolar um gato, eis a minha abordagem:
Código :
#!/usr/bin/env lua
local content =[=[
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
]=]localfunction split(str, sep)local result ={}local regex =("([^%s]+)"):format(sep)for each in str:gmatch(regex)do
table.insert(result, each)endreturn result
endlocal lines = split(content,"\n")for _,line in ipairs(lines)do
print(line)end
Saída :
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
Explicação :
A gmatchfunção funciona como um iterador, busca todas as strings correspondentes regex. A regextoma todos os caracteres até encontrar um separador.
function string:split(delimiter)local result ={}local from =1local delim_from, delim_to = string.find( self, delimiter, from )while delim_from do
table.insert( result, string.sub( self, from , delim_from-1))
from = delim_to +1
delim_from, delim_to = string.find( self, delimiter, from )end
table.insert( result, string.sub( self, from ))return result
end
delimiter = string.split(stringtodelimite,pattern)
Muitas dessas respostas aceitam apenas separadores de caractere único ou não lidam bem com casos extremos (por exemplo, separadores vazios); portanto, pensei em fornecer uma solução mais definitiva.
Aqui estão duas funções gsplite split, adaptadas do código na extensão Scribunto MediaWiki , que é usada em wikis como a Wikipedia. O código é licenciado sob a GPL v2 . Alterei os nomes das variáveis e adicionei comentários para tornar o código um pouco mais fácil de entender, e também alterei o código para usar padrões regulares de strings Lua em vez dos padrões de Scribunto para strings Unicode. O código original tem casos de teste aqui .
-- gsplit: iterate over substrings in a string separated by a pattern-- -- Parameters:-- text (string) - the string to iterate over-- pattern (string) - the separator pattern-- plain (boolean) - if true (or truthy), pattern is interpreted as a plain-- string, not a Lua pattern-- -- Returns: iterator---- Usage:-- for substr in gsplit(text, pattern, plain) do-- doSomething(substr)-- endlocalfunction gsplit(text, pattern, plain)local splitStart, length =1,#text
returnfunction()if splitStart thenlocal sepStart, sepEnd = string.find(text, pattern, splitStart, plain)local ret
ifnot sepStart then
ret = string.sub(text, splitStart)
splitStart =nilelseif sepEnd < sepStart then-- Empty separator!
ret = string.sub(text, splitStart, sepStart)if sepStart < length then
splitStart = sepStart +1else
splitStart =nilendelse
ret = sepStart > splitStart and string.sub(text, splitStart, sepStart -1)or''
splitStart = sepEnd +1endreturn ret
endendend-- split: split a string into substrings separated by a pattern.-- -- Parameters:-- text (string) - the string to iterate over-- pattern (string) - the separator pattern-- plain (boolean) - if true (or truthy), pattern is interpreted as a plain-- string, not a Lua pattern-- -- Returns: table (a sequence table containing the substrings)localfunction split(text, pattern, plain)local ret ={}for match in gsplit(text, pattern, plain)do
table.insert(ret, match)endreturn ret
end
Alguns exemplos da splitfunção em uso:
localfunction printSequence(t)
print(unpack(t))end
printSequence(split('foo, bar,baz',',%s*'))-- foo bar baz
printSequence(split('foo, bar,baz',',%s*',true))-- foo, bar,baz
printSequence(split('foo',''))-- f o o
function str_split(str, sep)if sep ==nilthen
sep ='%s'endlocal res ={}local func =function(w)
table.insert(res, w)end
string.gsub(str,'[^'..sep..']+', func)return res
end
Eu usei os exemplos acima para criar minha própria função. Mas a peça que faltava para mim estava escapando automaticamente dos personagens mágicos.
Aqui está a minha contribuição:
function split(text, delim)-- returns an array of fields based on text and delimiter (one character only)local result ={}local magic ="().%+-*?[]^$"if delim ==nilthen
delim ="%s"elseif string.find(delim, magic,1,true)then-- escape magic
delim ="%"..delim
endlocal pattern ="[^"..delim.."]+"for w in string.gmatch(text, pattern)do
table.insert(result, w)endreturn result
end
É tarde demais para esta pergunta, mas caso alguém queira uma versão que lide com a quantidade de divisões que você deseja obter .....
-- Split a string into a table using a delimiter and a limit
string.split =function(str, pat, limit)local t ={}local fpat ="(.-)".. pat
local last_end =1local s, e, cap = str:find(fpat,1)while s doif s ~=1or cap ~=""then
table.insert(t, cap)end
last_end = e+1
s, e, cap = str:find(fpat, last_end)if limit ~=niland limit <=#t thenbreakendendif last_end <=#str then
cap = str:sub(last_end)
table.insert(t, cap)endreturn t
end
Se você programa em Lua, está sem sorte aqui. Lua é A única linguagem de programação que é notoriamente infame porque seus autores nunca implementaram "a" função de divisão na biblioteca padrão e, em vez disso, escreveram 16 tela cheia de explicações e desculpas esfarrapadas de por que eles não fizeram e não o fizeram, intercalado com vários exemplos de semi-trabalho que são praticamente garantidos para trabalhar para quase todos, exceto na sua área de trabalho . Este é apenas o estado da arte de Lua, e todo mundo que programa em Lua simplesmente acaba cerrando os dentes e iterando sobre os personagens. Existem muitas soluções existentes às vezes melhores, mas exatamente zero soluções confiáveis .
Respostas:
Aqui está minha solução realmente simples. Use a função gmatch para capturar cadeias que contenham pelo menos um caractere de outra coisa que não seja o separador desejado. O separador é ** qualquer * espaço em branco (% s em Lua) por padrão:
.
fonte
'foo,,bar'
. Você obtém, em{'foo','bar'}
vez de{'foo', '', 'bar'}
function split(inputstr, sep) sep=sep or '%s' local t={} for field,s in string.gmatch(inputstr, "([^"..sep.."]*)("..sep.."?)") do table.insert(t,field) if s=="" then return t end end end
Se você estiver dividindo uma string em Lua, tente os métodos string.gmatch () ou string.sub (). Use o método string.sub () se você souber o índice no qual deseja dividir a string ou use o string.gmatch () se você analisará a string para encontrar o local em que ela será dividida.
Exemplo usando string.gmatch () do Manual de referência do Lua 5.1 :
fonte
Se você deseja apenas iterar sobre os tokens, isso é bastante interessante:
Resultado:
Breve explicação: o padrão "[^% s] +" corresponde a todas as seqüências não vazias entre os caracteres de espaço.
fonte
%S
é igual ao que você mencionou, assim como%S
a negação de%s
, assim como%D
a negação de%d
. Além disso,%w
é igual a[A-Za-z0-9_]
(outros caracteres podem ser suportados dependendo do seu código do idioma).Assim como
string.gmatch
encontrará padrões em uma string, esta função encontrará as coisas entre os padrões:Por padrão, ele retorna o que estiver separado por espaços em branco.
fonte
Aqui está a função:
Chame assim:
por exemplo:
Para mais informações, acesse:
http://lua-users.org/wiki/SplitJoin
fonte
Eu gosto desta solução curta
fonte
Como há mais de uma maneira de esfolar um gato, eis a minha abordagem:
Código :
Saída :
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Explicação :
A
gmatch
função funciona como um iterador, busca todas as strings correspondentesregex
. Aregex
toma todos os caracteres até encontrar um separador.fonte
Você pode usar este método:
fonte
Muitas dessas respostas aceitam apenas separadores de caractere único ou não lidam bem com casos extremos (por exemplo, separadores vazios); portanto, pensei em fornecer uma solução mais definitiva.
Aqui estão duas funções
gsplit
esplit
, adaptadas do código na extensão Scribunto MediaWiki , que é usada em wikis como a Wikipedia. O código é licenciado sob a GPL v2 . Alterei os nomes das variáveis e adicionei comentários para tornar o código um pouco mais fácil de entender, e também alterei o código para usar padrões regulares de strings Lua em vez dos padrões de Scribunto para strings Unicode. O código original tem casos de teste aqui .Alguns exemplos da
split
função em uso:fonte
um caminho não visto nos outros
fonte
Simplesmente sentado em um delimitador
fonte
Eu usei os exemplos acima para criar minha própria função. Mas a peça que faltava para mim estava escapando automaticamente dos personagens mágicos.
Aqui está a minha contribuição:
fonte
Você poderia usar a biblioteca do penlight . Isso tem uma função para dividir string usando o delimitador que gera a lista.
Ele implementou muitas das funções que podemos precisar durante a programação e a falta em Lua.
Aqui está a amostra para usá-lo.
fonte
Dependendo do caso de uso, isso pode ser útil. Corta todo o texto em ambos os lados das bandeiras:
Resultado:
fonte
É tarde demais para esta pergunta, mas caso alguém queira uma versão que lide com a quantidade de divisões que você deseja obter .....
fonte
Se você programa em Lua, está sem sorte aqui. Lua é A única linguagem de programação que é notoriamente infame porque seus autores nunca implementaram "a" função de divisão na biblioteca padrão e, em vez disso, escreveram 16 tela cheia de explicações e desculpas esfarrapadas de por que eles não fizeram e não o fizeram, intercalado com vários exemplos de semi-trabalho que são praticamente garantidos para trabalhar para quase todos, exceto na sua área de trabalho . Este é apenas o estado da arte de Lua, e todo mundo que programa em Lua simplesmente acaba cerrando os dentes e iterando sobre os personagens. Existem muitas soluções existentes às vezes melhores, mas exatamente zero soluções confiáveis .
fonte