Página 1 de 1

Saber se uma sequencia de Numeros/caracteres, tem repetentes

Enviado: 01 Jul 2021 13:42
por informais
Olá amigos, tudo bem

Preciso ler uma (string/Texto) que na verdade está armazenando dezenas, e que está separada por PIPE
Preciso saber quantas vezes e quais números repetem nela, separados por PIPE |

Exemplo veja a String/texto

04|09|16|23|39|43|80|85|94|99 nenhuma dezena se repete
30|30|30|30|30|01|01|01|01|01 Já nessa o 30 e 01 Repete várias vezes
04|04|16|23|39|43|80|85|94|99 04 - 2 Vezes
etc..

Preciso ter um retorno de qual(ais)dezena se Repetem

Exemplo a primeira seria assim Não tem Repetidos

Espero que tenham entendido

Essa informação está dentro de uma tabela campo Char, cada um em uma linha da tabela

Assim que fica no banco de dados

17|20|22|27|30|35|41|42|75|95
71|16|25|34|70|27|80|43|61|06
04|12|17|29|39|43|48|67|69|81
95|94|98|97|08|77|83|84|85|20
01|01|01|01|01|01|01|01|01|01
04|06|08|12|17|28|29|39|79|86
11|18|23|27|39|43|49|74|77|84
27|95|06|35|61|56|98|49|17|01
43|16|74|56|84|08|34|55|69|06
01|06|09|16|35|49|62|70|89|99
18|17|38|98|06|02|43|22|49|27
27|06|32|35|75|81|08|29|52|56
06|18|23|35|38|60|71|89|95|98
09|27|23|02|95|12|78|41|60|77
04|17|20|38|42|56|61|79|83|95
67|42|02|56|77|98|24|52|86|61
11|01|18|22|34|42|56|66|75|92
69|69|69|69|69|69|69|69|69|69
82|52|08|18|11|67|84|66|70|80
11|69|38|23|28|62|66|08|77|21
01|01|01|01|01|01|01|01|01|01
08|11|12|20|21|55|69|70|80|96
16|16|16|16|16|16|16|16|16|16
16|16|16|16|16|16|16|16|16|16
17|21|32|39|48|63|70|79|55|84
32|21|48|15|99|22|83|35|97|25
11|16|18|30|34|93|94|71|70|69
01|04|09|17|27|36|43|81|83|97
49|56|20|52|62|63|74|70|40|66
11|96|32|22|21|84|35|06|62|18
09|98|11|35|85|29|75|52|32|30
25|28|35|60|61|11|11|12|16|78
02|08|15|22|29|42|55|69|82|89

Saber se uma sequencia de Numeros/caracteres, tem repetentes

Enviado: 01 Jul 2021 17:57
por JoséQuintas
Em Clipper mesmo?

Se os números sempre estão com dois caracteres, um FOR/NEXT poderia ser usado.

Código: Selecionar todos

FOR nCont = 1 TO Len( cText ) STEP 3
   nNumero := Val( Substr( cText, nCont, 2 ) )
NEXT
Talvez um array pra armazenar os números e a quantidade de cada um, se a quantidade for importante.

Código: Selecionar todos

aList := {}
...
nPos := ASCan( aList, { | e | e[ 1 ] == nNumero } ) // a confirmar se no ASCan() do Clipper o parâmetro do codeblock é o primeiro
IF nPos == 0
  AAdd( aList, { nNumero, 1 } )
ELSE
   aList[ nPos, 2 ] += 1
ENDIF
Depois seria listar as quantidades maiores que 1

Código: Selecionar todos

FOR nCont = 1 TO Len( aList )
   IF aList[ nCont, 2 ] > 1
      ? "numero:", aList[ nCont, 1 ], "qtde:", aList[ nCont, 2 ]
   ENDIF
NEXT
Seria por aí, depende exatamente de como precisa do resultado.

Se fosse Harbour, poderia usar o hb_RegExSplit() pra separar os números mais rápido, e também o FOR/EACH, ou talvez AEval().

Saber se uma sequencia de Numeros/caracteres, tem repetentes

Enviado: 01 Jul 2021 18:58
por ANDRIL
Veja se é isso que procura, creio que deva compilar normalmente em Clipper.

Código: Selecionar todos


txt = "04|09|16|23|39|43|80|85|94|99|30|30|30|30|30|01|01|01|01|01|04|04|16|23|39|43|80|85|94"
aNum = Split(txt)
aSort(aNum)

maximo=len(aNum)
aSaida:={}
for i=1 to maximo
	pos=ascan(aSaida,{|e| e[1]=aNum[i]})
	if pos=0
	aadd(aSaida,{aNum[i],1})
	else
	aSaida[pos][2]+=1
	endif
next

for i=1 to len(aSaida)
	? aSaida[i][1], aSaida[i][2]
next
wait"veja o resultado"

*******************
Function Split(txt)
*******************
//txt = "04|09|16|23|39|43|80|85|94|99|30|30|30|30|30|01|01|01|01|01|04|04|16|23|39|43|80|85|94"
txt = iif(!"|"$txt,txt+"|",txt)
aNum:={}
do while len(txt)>0 
	pos=AT("|",txt)
	if pos>0
		num=substr(txt,1,AT("|",txt)-1)
	else
		num=txt
		txt=""
	endif
	aadd(aNum,num)

	if !"|"$txt
	exit
	endif

	pos=AT("|",txt)
	txt=substr(txt,AT("|",txt)+1)
enddo
return aNum

Saber se uma sequencia de Numeros/caracteres, tem repetentes

Enviado: 02 Jul 2021 11:05
por informais
Olá amigo ANDRIL

A principio exatamente o que quero, agora é Adptar a minha realidade

Saber se uma sequencia de Numeros/caracteres, tem repetentes

Enviado: 02 Jul 2021 14:10
por JoséQuintas
A função Split ficou meio confusa.
Talvez melhor assim:

Código: Selecionar todos

FUNCTION Split( cTxt )

LOCAL aList := {}

cTxt := Trim( cTxt )
IF Right( cTxt, 1 ) != "|" .AND. Len( cTxt ) > 1
  cTxt += "|"
ENDIF
DO WHILE "|" $ cTxt
   nPos := At( "|", cTxt )
   cNum := Substr( cTxt, 1, nPos - 1 )
   cTxt  := Substr( cTxt, nPos + 1 )
   AAdd( aList, cNum )
ENDDO

RETURN aList

Saber se uma sequencia de Numeros/caracteres, tem repetentes

Enviado: 03 Jul 2021 01:38
por alxsts
Olá!

Segue a minha versão da rotina:
Capturar.JPG

Código: Selecionar todos

// Preciso ler uma (string/Texto) que na verdade está armazenando dezenas, 
// e que está separada por PIPE
// Preciso saber quantas vezes e quais números repetem nela, separados por PIPE |
#include "setcurs.ch"

PROCEDURE Duplicados()
   // Alexandre Santos - Fórum PC Toledo
   LOCAL cDup, cString, nLimit, nOuter, cSearch
   LOCAL nCount, nInner, nOffSet, cOldColor, nOldCursor

   RELEASE GetList
   REQUEST DBFCDX
   RDDSETDEFAULT( "DBFCDX" )

   cOldColor  := SetColor( "W+/B,B/W" ) ; CLS
   nOldCursor := SC_NONE

   If ! File( "DEZENAS.DBF" )
      DbCreate("Dezenas", { { "Dezenas", "C", 29, 0 }, { "Duplicados", "C", 80, 0 } }, "DBFCDX" )

      DBUSEAREA( .T., "DBFCDX", "DEZENAS", "DEZENAS", .F. )

      DbAppend() ;  DEZENAS->dezenas := "17|20|22|27|30|35|41|42|75|95"
      DbAppend() ;  DEZENAS->dezenas := "71|16|25|34|70|27|80|43|61|06"
      DbAppend() ;  DEZENAS->dezenas := "04|12|17|29|39|43|48|67|69|81"
      DbAppend() ;  DEZENAS->dezenas := "95|94|98|97|08|77|83|84|85|20"
      DbAppend() ;  DEZENAS->dezenas := "01|01|01|01|01|01|01|01|01|01"
      DbAppend() ;  DEZENAS->dezenas := "04|06|08|12|17|28|29|39|79|86"
      DbAppend() ;  DEZENAS->dezenas := "11|18|23|27|39|43|49|74|77|84"
      DbAppend() ;  DEZENAS->dezenas := "27|95|06|35|61|56|98|49|17|01"
      DbAppend() ;  DEZENAS->dezenas := "43|16|74|56|84|08|34|55|69|06"
      DbAppend() ;  DEZENAS->dezenas := "01|06|09|16|35|49|62|70|89|99"
      DbAppend() ;  DEZENAS->dezenas := "18|17|38|98|06|02|43|22|49|27"
      DbAppend() ;  DEZENAS->dezenas := "27|06|32|35|75|81|08|29|52|56"
      DbAppend() ;  DEZENAS->dezenas := "06|18|23|35|38|60|71|89|95|98"
      DbAppend() ;  DEZENAS->dezenas := "09|27|23|02|95|12|78|41|60|77"
      DbAppend() ;  DEZENAS->dezenas := "04|17|20|38|42|56|61|79|83|95"
      DbAppend() ;  DEZENAS->dezenas := "67|42|02|56|77|98|24|52|86|61"
      DbAppend() ;  DEZENAS->dezenas := "11|01|18|22|34|42|56|66|75|92"
      DbAppend() ;  DEZENAS->dezenas := "69|69|69|69|69|69|69|69|69|69"
      DbAppend() ;  DEZENAS->dezenas := "82|52|08|18|11|67|84|66|70|80"
      DbAppend() ;  DEZENAS->dezenas := "11|69|38|23|28|62|66|08|77|21"
      DbAppend() ;  DEZENAS->dezenas := "01|01|01|01|01|01|01|01|01|01"
      DbAppend() ;  DEZENAS->dezenas := "08|11|12|20|21|55|69|70|80|96"
      DbAppend() ;  DEZENAS->dezenas := "16|16|16|16|16|16|16|16|16|16"
      DbAppend() ;  DEZENAS->dezenas := "16|16|16|16|16|16|16|16|16|16"
      DbAppend() ;  DEZENAS->dezenas := "17|21|32|39|48|63|70|79|55|84"
      DbAppend() ;  DEZENAS->dezenas := "32|21|48|15|99|22|83|35|97|25"
      DbAppend() ;  DEZENAS->dezenas := "11|16|18|30|34|93|94|71|70|69"
      DbAppend() ;  DEZENAS->dezenas := "01|04|09|17|27|36|43|81|83|97"
      DbAppend() ;  DEZENAS->dezenas := "49|56|20|52|62|63|74|70|40|66"
      DbAppend() ;  DEZENAS->dezenas := "11|96|32|22|21|84|35|06|62|18"
      DbAppend() ;  DEZENAS->dezenas := "09|98|11|35|85|29|75|52|32|30"
      DbAppend() ;  DEZENAS->dezenas := "25|28|35|60|61|11|11|12|16|78"
      DbAppend() ;  DEZENAS->dezenas := "02|08|15|22|29|42|55|69|82|89"
      DbAppend() ;  DEZENAS->dezenas := "55|08|15|02|29|08|55|15|42|08"
                                     //  0...x....1....x....2....x...2
                                     //  12345678901234567890123456789
   Else      
      DBUSEAREA( .T., "DBFCDX", "DEZENAS", "DEZENAS", .F. )
   Endif

   DEZENAS->( DbGoTop() )

   nOffSet := 3

   // percorre os registros
   While ! DEZENAS->( Eof() )
      cDup    := ""
      cString := DEZENAS->dezenas
      nLimit  := Len( cString )
      nOuter  := 1

      // loop externo... percorre as dezenas de cada registro
      While nOuter < nLimit
         cSearch := SubStr( cString, nOuter, 2 )
         nInner := 1
         nCount := 0
         // loop interno... conta cada dezena nas dezenas do registro atual
         While nInner < nLimit
            If Substr( cString, nInner, 2 ) == cSearch
               nCount++
            Endif
            nInner += nOffSet
         Enddo
         // se encontrou mais que um
         If nCount > 1
            // se é a primeira vez que encontrou, guarda
            If At( cSearch + ":", cDup ) == 0
               cDup += If( ! Empty( cDup ), ", ", "" ) + cSearch + ":" + LTrim( Str( nCount ) )
            Endif
         Endif
         nOuter += nOffSet
      Enddo  // nOuter < nLimit
      // se encontrou, grava no próprio registro (arquivo aberto em modo exclusivo)
      If ! Empty( cDup )
         DEZENAS->Duplicados := cDup
      Endif
      // avança registro
      DEZENAS->( DbSkip() )
   Enddo  // ! DEZENAS->( Eof() )

   // exibe registros, fecha arquivo
   DEZENAS->( Browse(), DbCloseArea() )

   // restaura tela
   SetColor( cOldColor ) ; CLS ; SetCursor( nOldCursor )

RETURN
//----------------------------------------------------------------------------------------------------
JoséQuintas escreveu:A função Split ficou meio confusa.
Segue a minha versão:

Código: Selecionar todos

//----------------------------------------------------------------------------------------------------
FUNCTION aTokens( cString, cDelimiter )
   // Alexandre Santos - Fórum PC Toledo
   LOCAL aTokens := {}, nPos, nLen

   If Valtype( cString ) == "C" .And. ( ! Empty( cString := Alltrim( cString ) ) )
      If Valtype( cDelimiter ) == "C" .And. ( ! Empty( cDelimiter ) )
         While ( nPos := At( cDelimiter, cString ) ) > 0
            AAdd( aTokens, SubStr( cString, 1, nPos - 1 ) )
            cString := SubStr( cString, nPos + 1 )
         Enddo
         AAdd( aTokens, cString )
      Else
         // sem delimitador... retorna byte a byte
         nLen := Len( cString )
         For nPos := 1 To nLen
            AAdd( aTokens, SubStr( cString, nPos, 1 ) )
         Next
      Endif
   Endif

RETURN aTokens
//----------------------------------------------------------------------------------------------------
informais escreveu:Preciso saber quantas vezes e quais números repetem nela, separados por PIPE |
Não ficou claro se o retorno também é uma string com o resultado separado por pipes. Mas isto é fácil de adaptar...

Saber se uma sequencia de Numeros/caracteres, tem repetentes

Enviado: 07 Jul 2021 12:59
por informais
Obrigado a todos,
Fiz um Apanhado das dicas dos amigos e está resolvido