Páginas (2): 1 2   
gambafeliz   11-06-2021, 09:55
#1
Hola,

Tengo varios problemas de lentitud en varios trozos de código y os voy a poner uno por si me pueden ayudar. Gracias.

¿Sería posible acelerar esto?

Código:
' cadena por ejemplo se le pasa -32,40 €
Public Function soloNumeros(cadena As String) As String

   Dim n As Integer
   Dim sCadena As String

   For n = 0 To Len(cadena)
      If IsDigit(cadena[n]) Or If cadena[n] = "." Or If cadena[n] = "," Or If cadena[n] = "-" Then sCadena &= cadena[n]
   Next
   Return IIf(sCadena = "", "0", sCadena)

End
Última modificación: 11-06-2021, 16:57 por gambafeliz.
vuott   11-06-2021, 15:17
#2
Confused ...podemos quitar un elemento:

[code]

...y, si está absolutamente seguro de que el carácter "/" nunca estará presente en la cadena de caracteres entre los números, pasada a la función "soloNumeros()", entonces podemos eliminar un otro elemento:
[code]
Última modificación: 11-06-2021, 17:10 por vuott.

« Los horizontes perdidos nunca regresan. » (F. Battiato, 1983)

« Las ondas nunca regresan. » (Genesis: Ripples, 1976)

« Vita non suavis esse potest, nec Mors amara. »  (...vuott)
Shordi   11-06-2021, 16:09
#3
Tras probar varios enfoques, el original es el más rápido... dependiendo de lo que le pongas. Sin embargo como está, supongo, destinado a depurar cadenas cortas casi siempre numéricas, ahí es el más rápido por los atajos decisivos de "or if" porque la mayoría de los caracteres no pasa de isdigit() y no hay que mirar más.

saludos
Código:
 

No podemos regresar
vuott   11-06-2021, 16:18
#4
(11-06-2021, 15:17)vuott escribió: si está absolutamente seguro de que el carácter "/" nunca estará presente en la cadena de caracteres entre los números

...o mejor:

Código:
Public Function soloNumeros(cadena As String) As String
 
   Dim n As Integer
 
   For n = 0 To Len(cadena)
     If (Asc(cadena[n]) < 44) Or (Asc(cadena[n]) > 57) Then Mid(cadena, n + 1, 1) = Null
   Next
   
   Return cadena
 
End

...o si prefieres sin la palabra-llave "Return": Big Grin

Código:
Public Sub Main()

  Dim cadena As String = "-32.40€"
  Dim bb As New Byte[]
  
  bb = bb.FromString(cadena)

  soloNumeros(bb)
  
  Print bb.ToString(0, bb.Find(0))

End 


Private Function soloNumeros(cadena As Byte[])
 
   Dim n As Integer
 
   For n = 0 To cadena.Max
     If (cadena[n] < 44) Or (cadena[n] > 57) Then cadena[n] = 0
   Next
 
End
Supongo que esta última función entre aquellas mias, no teniendo funciones nativas de cadena, sea la más rápida.
Última modificación: 11-06-2021, 17:10 por vuott.

« Los horizontes perdidos nunca regresan. » (F. Battiato, 1983)

« Las ondas nunca regresan. » (Genesis: Ripples, 1976)

« Vita non suavis esse potest, nec Mors amara. »  (...vuott)
cogier   11-06-2021, 16:39
#5
La velocidad de esto ya es muy rápida. Tuve que pasar por un millón de ejemplos para obtener un resultado de velocidad razonable. He puesto una solución ligeramente diferente, (If IsNumber(cadena[n]) Then sCadena &= cadena[n]) pero la diferencia de velocidad es insignificante. 

Prueba este código.Tendrás que cambiar el formato del número en la línea 51.

Código:
' Gambas class file

Public Sub Form_Open()

  Dim fStart, fFinish As Float
  Dim sData As String[]
  Dim iLoop As Integer
  Dim sNull As String
  
  Me.Center

  If Not Exist(Application.Path &/ "data.txt") Then CreateNos
  sData = Split(File.Load(Application.Path &/ "data.txt"), gb.NewLine, "", True)

  fStart = CFloat(Now)

  For iLoop = 0 To sData.Max
    sNull = soloNumeros(sData[iLoop])
  Next

  fFinish = CFloat(Now)
  Print DateDiff(fStart, fFinish, gb.Millisecond) & " milisegundos"

End

' cadena por ejemplo se le pasa -32,40 €
Public Function soloNumeros(cadena As String) As String

  Dim n As Integer
  Dim sCadena As String

  For n = 0 To Len(cadena)
    'If IsDigit(cadena[n]) Or If cadena[n] = "." Or If cadena[n] = "," Or If cadena[n] = "-" Then sCadena &= cadena[n]
    If IsNumber(cadena[n]) Then sCadena &= cadena[n]
  Next

  Return IIf(sCadena = "", "0", sCadena)

End

Public Sub CreateNos()

  Dim iLoop As Integer
  Dim sTemp As String
  Dim sNumbers As New String[]

  For iLoop = 0 To 1000000
    sTemp = ""
    If Rand(1, 2) = 1 Then sTemp = "-"
    sTemp &= Str(Rand(0, 99999) / 100)
    sNumbers.Add(Format(sTemp, "#0.00 €")) ''************************************************
  Next

  File.Save(Application.Path &/ "data.txt", sNumbers.Join(gb.NewLine))

End
gambafeliz   11-06-2021, 16:54
#6
Gracias por vuestro esfuerzo. Por Dios, muchisimas gracias chicos. Incluso me he emocionado. GRACIAS.

Tras mirarlo más y gracias a vuestros puntos de vista. Me temo que no es posible acelerarlo más.

1. Necesito que me devuelva obligatoriamente "0" ó la cadena depurada donde solo admito números y su signo así como el punto y la coma.
2. Y sí es posible que este todo tipo de caracteres, intento justo depurar toda cadena para saber si es un número tal como yo lo defino.

Al final he detectado mi problema de lentitud y estoy justo ahora intentando resolverlo. Principalmente es desconocimiento de la base de datos SQLite. Os lo cuento por si detectan algo en mi conversación.

Estoy agrupando importes por su categoría y subcategoría. Pero es para cargar un grid por mes y siempre por el año actual. Tenia que crear varias View en concreto 3 para poder obtener un select final.

Además cuando creaba una vista después al final la destruia para crear el siguiente mes. En fin, esto hacia que un ordenador pensara al menos 4 segundo para cargar 12 meses. Y como me he hecho un pendrive con Debian 10 y así ejecutar Gambas IDE donde yo quiera para disfrutar mi maravilloso Gambas sin limites Smile pues en el pendrive incluso tenia que esperar 1 minuto para ver 12 meses. Una locura. Ojala supiera como acelerar a tope mi pendrive. Esto ocurre en cualquier ordenador, ya lo he probado. Sad

Me acabo de dar cuenta que si guardo el año actual en configuración de la aplicación y cada vez que ejecuto esta opción de 12 meses miro si el año ya lo guardé en configuración y utilizo las vistas sin destruirlas para tan solo cargar un pequeño select para cada mes. Así creo que será incluso instantaneo.

Pero que tontito fue para no verlo.
Última modificación: 11-06-2021, 16:56 por gambafeliz.
omoreno   11-06-2021, 17:03
#7
Hola gambafeliz

Hay que agregar los caracteres en el array simbolos.

Código:
Public Function soloNumeros(cadena As String) As String
  Dim simbolos As String[] = [" ", "€", "$", "¥", "¢", "£"]
  For Each s As String In simbolos
    cadena = Trim(Replace(cadena, S, ""))
  Next  
  cadena = Format(Val(cadena), "0.00")
  Return cadena
End

Saludos.
gambafeliz   11-06-2021, 19:36
#8
Gracias omoreno lo voy a mirar Smile
vuott   11-06-2021, 20:11
#9
De todas formas, debes aclarar qué posibles cadenas se pasan a la función.
¿Cualquier tipo de cadena?
O solo algunas cadenas ? Es decir:
esta forma (por ejemplo) "€3,123" es posible ?
Esta ? "€3,123w"
Esta ? "wsde"
Esta ? "3w,45€"

« Los horizontes perdidos nunca regresan. » (F. Battiato, 1983)

« Las ondas nunca regresan. » (Genesis: Ripples, 1976)

« Vita non suavis esse potest, nec Mors amara. »  (...vuott)
gambafeliz   11-06-2021, 23:25
#10
Oye vuott primero lo primero aunque se que no eres Futbolero mi enhorabuenas por ganar tu Selección a Turquía. Bravoooo. Smile

Te cuento esta función le paso hasta arroz con cigalas por que es un mero filtro de campos de mi tabla y simplemente le paso columnas de mi tabla para definir.

Mira vuott aunque en la línea anterior afirmo eso que he dicho, es mentira, y ¿por qué? porque acabo de filtra mi Function que nombro en la pregunta y solo le paso cadenas con posibles números con número, signos (+,-) y símbolos monetarios y veo que nada más. Por lo que lo hago por aquello de por si acaso paso algo que no esperaba. Con lo cual os pido disculpa si os he liado o confundido, por su puesto no era mi intensión. Ya sabéis que os aprecio de verdad.

Espero que te haya contestado todo lo que necesitas, joven.

Saludos.
Páginas (2): 1 2   
  
Usuarios navegando en este tema: 3 invitado(s)
Powered By MyBB, © 2002-2024 MyBB Group.
Made with by Curves UI.