Italian Array con indice letterale

MaAncheNo

Member
Licensed User
Longtime User
Buonasera,

ho provato a cercare se esistessero in b4a gli array con indice letterale ma non ho trovato nulla.
Non so bene come spiegarlo ma in pascal sarebbe:
B4X:
var
dizionario :Array ['A'..'Z'] of Integer;

Dovrei cioè avere la possibilità di recuperare un intero passando l'indice alfanumerico.
Purtroppo non serve la conversione e/o modifica del codice ascii del carattere in quanto la sequenza numerica non è lineare.
 

Star-Dust

Expert
Licensed User
Longtime User
No, Mi spiace non esiste, ma puoi usare qualche trucco per ottenere qualcosa di simile.
Ad esempio con le Map

O passare a Delphi che li ha
 

Star-Dust

Expert
Licensed User
Longtime User
Un altra Soluzione
B4X:
Dim Indice As List = Array As String("A","B","Z") ' Tua lista alfanumerica
Dim Dizionario() As Int

Sub Cerca(Chiave As String) As Int
    Dim A As Int = Indice.IndexOf("Chiave")
   
    If a>-1 Then 
        Return Dizionario(a)
    Else
        Return -255
    End If
End Sub

Sub Assegna(Chiave As String, Valore As Int)
    Dim A As Int = Indice.IndexOf("Chiave")
   
    If a>-1 Then Dizionario(a)=Valore
End Sub
 

MaAncheNo

Member
Licensed User
Longtime User

Grazie! Anche questa mi farà comodo, però dato che è del tutto diversa dalla prima mi fa venire in mente un'altra domanda.... spero di non dover aprire appositamente un altro thread...

Tra la prima e la seconda soluzione c'è molta differenza......
Tanto tanto tempo addietro esisteva la modalità di compilazione Tiny e Fast, ovvero il compilatore cercava di ridurre il codice in uscita o se ne fregava premiando la velocità e gli esempi sopra lo dimostrano.
Il primo esempio mi genera un codice veloce anche se molto lungo (Mappa di 26 elementi) il secondo molto più compatto.
Cosa si deve prediligere con le risorse attuali dei dispositivi? Velocità o compattezza?
 

Star-Dust

Expert
Licensed User
Longtime User
Devi aprire un altro post, rischiamo che vengano cancellate le risposte.

Facendo un eccezione, 20 anni fà si faceva sempre riferimento alla compattezza perché i pc dell'epoca avevano poche risorse.
Adesso il riferimento assoluto che sia bello da vedere anche se non funziona.... quindi non saprei dirti...

Su che dispositivi deve girare? che risorse di memoria hanno? Lavoreranno su Archivi grandi ? richiederà velocità?
Quanto è grande la lista alfanumerica, 26 quanto le lettere dell'alfabeto o più grande?

Il secondo esempio si può velocizzare, l'ho buttato giù cosi sul forum e senza provarlo.
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Puoi ridurre il codice della Map, inizializzando la Map con un Ciclo For,

B4X:
Dim M As Map

M.Initialize
For i= 0 To 26
   M.Put(Chr(65+i),0)
Next

Altro
B4X:
Dim Indice() As String = Array As String("A","B","Z") ' Tua lista alfanumerica
Dim M As Map

M.Initialize
For i= 0 To Indice.Size
   M.Put(Indice(i),0)
Next
 

MaAncheNo

Member
Licensed User
Longtime User
No, purtroppo non funzionano.
Non perché siano sbagliate ma perché come dicevo la sequenza numerica non è lineare, i numeri gemelli (11, 22, 33.. etc) vengono saltati.
Per il momento ho risolto solo con:
B4X:
    Select code_char
        Case "A"
            result = 10
        Case "B"
            result = 12
        ... etc ...   
    End Select
Ma fa veramente schifo.....
 

Star-Dust

Expert
Licensed User
Longtime User
Se fai due liste?

B4X:
Dim Indice as List = Array As String("A","B","Z") ' Tua lista alfanumerica
Dim Value() as int = Array of Int (10,12,14)


Dim CercaLettera as String="A"
Dim Valore as int =Value(Indice.IndexOf(CercaLettera))
 

Star-Dust

Expert
Licensed User
Longtime User
Altro
B4X:
    Dim Indice() As String= Array As String("A","B","Z") ' Tua lista alfanumerica
    Dim Value() As Int = Array As Int (10,12,14)

    Dim M As Map

    M.Initialize
    For i= 0 To Indice.Size
        M.Put(Indice(i),Value(i))
    Next

Le soluzioni sono molte, basta rifletterci sopra e avere un pizzico di fantasia e tanta fortuna
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Altro ancora

B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    Dim LetteralIndex As MyMap

    'Inserimento
    LetteralIndex.Initialize
    LetteralIndex.Add("A",10).Add("B",20).Add("Z",30)
    'Ricerca
    LetteralIndex.Map.GetKeyAt(0)
    LetteralIndex.Map.GetValueAt(0)
    Log(LetteralIndex.Map.Get("a"))
End Sub

Aggiungi una classe di nome MyMap
B4X:
Sub Class_Globals
    Dim M As Map
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    M.Clear
End Sub

Public Sub Add(Key As Object, Value As Object) As MyMap
    M.Put(Key,Value)
    Return Me
End Sub

Public Sub Map As Map
    Return M
End Sub

Ti servono altri esempi? te lo posso fare in altre decine di modi differenti
 

Attachments

  • LiteralIndex.zip
    6.4 KB · Views: 257

MaAncheNo

Member
Licensed User
Longtime User
No, no..... direi che bastano!!!
E visto che in parte lo hai fatto tu....... ecco il risultato:

Algoritmo di controllo validità del codice numerico di un container...

B4X:
public Sub ISO_6346_Ck(CtrNum As String) As Boolean
    Dim acc, ax, checkdigit As Int
    Dim remx, s, i As Int
    Dim b As Boolean
    Dim Indice() As String= Array As String("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
    Dim Value() As Int = Array As Int (10,12,13,14,15,16,17,18,19,20,21,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38)
    Dim M As Map
    M.Initialize
    ' Carica il vettore dei valori alfanumerici -> Star-Dust mode :)
    For i= 0 To Indice.Length - 1
        M.Put(Indice(i),Value(i))
    Next
    acc = 0
    s = 0
    ' Esegue l'algoritmo per il check dei primi 10 valori
    For i = 0  To 9 
        ' L'algoritmo prevede la moltiplicazione con 2^n e per n da 0 a 9
        s = Power(2, i)
        ' Le prime quattro sono lettere
        If i < 4 Then
            ax = M.Get(Indice(Asc(CtrNum.CharAt(i))-65)) * s
        Else       
            ' I restanti 6 sono numeri
            ax = (Asc(CtrNum.CharAt(i)) - 48) * s
        End If
    acc = acc + ax
    Next
    remx = (Floor(acc) Mod 11) Mod 10
    ' Estrazione check digit e conversione in numero
    checkdigit = Asc(CtrNum.CharAt(10))-48
    ' Controllo tra calcolato e inserito (ultima cifra)
    If (CtrNum.Length = 11) And (remx = checkdigit) Then
        b = True
    End If
    Return (b)
End Sub
 

Star-Dust

Expert
Licensed User
Longtime User
1) A cosa ti serve floor se non hai variabili dichiarate double ne float ma tutto è dichiarato int?

B4X:
remx = (Floor(acc) Mod 11) Mod 10
non sarebbe meglio
B4X:
remx = (acc Mod 11) Mod 10
 
Last edited:

udg

Expert
Licensed User
Longtime User
Volendo potresti risparmiarti anche l'array Indice e la Map.
Infatti, considerando che i suoi valori sono noti ed ordinati, ti basterebbe un'espressione tipo:
B4X:
Indice = "K"  'esempio
num = Value(Asc(Indice) - 65)
'che nel tuo caso si ridurrebbe a qualcosa tipo
ax = Value(Asc(CtrNum.CharAt(i))-65) * s

bye
 

MaAncheNo

Member
Licensed User
Longtime User
Ecco l'errore!!! Non tanto il Floor ma quanto:

B4X:
    Dim acc, ax As Double
    Dim remx, s, i, checkdigit As Int

Grazie!
 

MaAncheNo

Member
Licensed User
Longtime User
Si, ma sui "salti" dei gemelli? Mentre il vettore letterale è consecutivo quello numerico no.
 

Star-Dust

Expert
Licensed User
Longtime User
Stamattina presto ho provato l'algoritmo su Wikipedia e visto che aveva ancora la mente lucida, l'ho studiato. E non mi sembra di aver visto la necessità di dichiarare numero reale visto che sono tutte le elevazioni a Potenza di numeri interi
 
Last edited:

MaAncheNo

Member
Licensed User
Longtime User
Su wiki ho trovato un esempio in VB:
B4X:
Function ISO6346Check(k As String) ' Calculates the ISO Shipping Container Check Digit
Dim i%, s&
Application.Volatile
For i = 1 To 10
s = s + IIf(i < 5, Fix(11 * (Asc(Mid(k, i)) - 56) / 10) + 1, Asc(Mid(k, i)) - 48) * 2 ^ (i - 1)
Next i
ISO6346Check = (s - Fix(s / 11) * 11) Mod 10
End Function
Sarebbe ancora più compatta ma necessita di traduzione VB->B4A
Stanotte se ho tempo ci riprovo...
 

udg

Expert
Licensed User
Longtime User
Non mi è chiaro.
Quello che scrivevo era solo per dire che non avevi bisogno di una mappa o un array per cercare il riferimento numerico di una particolare lettera visto che potevi ricavare l'indice nell'array dei valori direttamente dalla lettera.

Se esiste un problema dove un codice tipo AKKT12345 deve essere letto come AKT123, ovvero sostituendo la doppia K con una sola, allora bisognerebbe lavorare sul codice in ingresso e fornirlo "ripulito" all'alagoritmo del checkdigit che hai già preparato.
Ti serve aiuto su questo punto? Eliminare da una stringa dei doppioni (o multipli) ?
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…