Italian XCLV, come verificare se due item (valori) della lista sono uguali?

XorAndOr

Active Member
Licensed User
Longtime User
Ciao a tutti.
Ho una XCLV con dei nomi, vorrei fare un controllo su questi nomi
e avvisare (anche per ora con un log) se nella lista esiste un nome
uguale ad un'altro già inserito nella lista.
Ho usato una variabile List per prendere i dati
non so se è il metodo corretto.
Allegare il progetto è un po' complicato
perche' i dati mi arrivano da un database esterno.
Gentilmente mi potreste aiutare? grazie

B4X:
Dim Item_Squadra As List   
Item_Squadra.Initialize

    For i = 0 To Clv_Item_Squadra.Size - 1
                
        Item_Squadra.AddAll(Array As String(Clv_Item_Squadra.GetPanel(i).GetView(0).Getview(0).text))
            
        Log(Item_Squadra.Get(i))' <----- Qui ho tutti i record (item) (valori) della xclv
        
    Next
 

LucaMs

Expert
Licensed User
Longtime User
Uhm... non tanto.

1 - Nel caso dovresti usare Add e non AddAll; quest'ultimo serve ad aggiungere alla list più valori con un'unica istruzione ma tu ne aggiungi uno solo (... .text)
2 - Alla fine del ciclo For avresti sì una lista in cui controllare se esistano doppioni ma non sapresti a quali item della CLV si riferiscano.

Vedo che prendi il valore di una View; se questo fosse lo stesso che tu associ ad ogni item nel momento in cui crei quest'ultimo (Clv_Item_Squadra.Add(..., Value), potresti fare, più semplicemente:
B4X:
For Each Item As CLVItem In Clv_Item_Squadra
    Item_Squadra.Add(Item.Value)
Next
ma ancora col problema di cui al punto 2.

Usando una Map anziché una List potresti associare i valori agli indici degli item:
B4X:
Dim Item_Squadra As Map
Item_Squadra.Initialize

For i = 0 To Clv_Item_Squadra.Size - 1
    Dim Item As CLVItem = Clv_Item_Squadra.GetRawListItem(i)
    Item_Squadra.Put(Item.Value, i)
Next

Meglio ancora, senza nemmeno memorizzare in una List o Map, sfruttare GetRawListItem che appunto avrebbe già i dati che ti servono.
 

XorAndOr

Active Member
Licensed User
Longtime User
1 - Nel caso dovresti usare Add e non AddAll; quest'ultimo serve ad aggiungere alla list più valori con un'unica istruzione ma tu ne aggiungi uno solo (... .text)
2 - Alla fine del ciclo For avresti sì una lista in cui controllare se esistano doppioni ma non sapresti a quali item della CLV si riferiscano.

Vedo che prendi il valore di una View; se questo fosse lo stesso che tu associ ad ogni item nel momento in cui crei quest'ultimo (Clv_Item_Squadra.Add(..., Value), potresti fare, più

Usando una Map anziché una List potresti associare i valori agli indici degli item:
B4X:
Dim Item_Squadra As Map
Item_Squadra.Initialize

For i = 0 To Clv_Item_Squadra.Size - 1
    Dim Item As CLVItem = Clv_Item_Squadra.GetRawListItem(i)
    Item_Squadra.Put(Item.Value, i)
Next
grazie LucaMs, ho usato AddAll perchè ho visto che avevo i valori della lista.
Ma posso usare anche Add.
Ho fatto una prova col secondo codice che mi hai postato
ma con Log(Item.Value) mi ritorna 26, 26, 26, 26 su 4 item inseriti nella xclv.
Col mio codice(sbagliato) mi ritorna i valori in formato testo come vorrei.
e poi questi valori fare un confronto se un item è uguale all'altro
(questa parte mi è complicata!)
 

Elric

Well-Known Member
Licensed User
Se ho capito bene, hai un codice che riempie una CLV da database esterno e vuoi controllare se ci sono valori duplicati e, se si, che ti avverta tramite log?

Se la lista non è troppo lunga, un accrocchio a forza bruta potrebbe fare al caso tuo (un ciclo for annidiato dentro un altro ciclo for):
B4X:
    For i = 0 To Clv_Item_Squadra.Size - 1
        Private Item1 As CLVItem = Clv_Item_Squadra.GetRawListItem(i)
        If (i + 1) = (Clv_Item_Squadra.Size - 1) Then
            Exit
        End If
       
        Private Contatore As Int
       
        For ii = (i + 1) To Clv_Item_Squadra.Size - 1
            Private Item2 As CLVItem = Clv_Item_Squadra.GetRawListItem(ii)
            If Item2.Value = Item1.Value Then
                Contatore = Contatore + 1
                ' Exit ' ---> se non interessa sapere quante volte è ripetuto basta uscire dal secondo ciclo for e sostituire il log oppure usare un valore boolean etc..
            End If
        Next
        Log($"${Item1.Value} presente ${Contatore} volte"$)
    Next
* ATTENZIONE! L'ho scirtto direttamente nell'editor del forum e non l'ho testato

Fermo quanto suggerito già da LucaMs, perché non curi la cosa a livello di database esterno con la sintassi MySQL, con un "SELECT count" ad esempio?
 

XorAndOr

Active Member
Licensed User
Longtime User
Se ho capito bene, hai un codice che riempie una CLV da database esterno e vuoi controllare se ci sono valori duplicati e, se si, che ti avverta tramite log?

Se la lista non è troppo lunga, un accrocchio a forza bruta potrebbe fare al caso tuo (un ciclo for annidiato dentro un altro ciclo for):
B4X:
    For i = 0 To Clv_Item_Squadra.Size - 1
        Private Item1 As CLVItem = Clv_Item_Squadra.GetRawListItem(i)
        If (i + 1) = (Clv_Item_Squadra.Size - 1) Then
            Exit
        End If
      
        Private Contatore As Int
      
        For ii = (i + 1) To Clv_Item_Squadra.Size - 1
            Private Item2 As CLVItem = Clv_Item_Squadra.GetRawListItem(ii)
            If Item2.Value = Item1.Value Then
                Contatore = Contatore + 1
                ' Exit ' ---> se non interessa sapere quante volte è ripetuto basta uscire dal secondo ciclo for e sostituire il log oppure usare un valore boolean etc..
            End If
        Next
        Log($"${Item1.Value} presente ${Contatore} volte"$)
    Next
* ATTENZIONE! L'ho scirtto direttamente nell'editor del forum e non l'ho testato

Fermo quanto suggerito già da LucaMs, perché non curi la cosa a livello di database esterno con la sintassi MySQL, con un "SELECT count" ad esempio?
Grazie Elric, ho provato il tuo codice e funziona benissimo. Sarebbe fantastico se potessi prelevare il nome dell'item anche perchè facendo il log (tuo codice)
mi scrive ' 26 presente 2 volte ' . quel 26 come faccio a prelevare il nome dell'item (valore) della xclv?. ma anche con il codice che hai postato sono mooolto avanti grazie.
P.s. per quanto riguardo perchè non uso la query di selezione è perchè i dati del DB mi servono tutti.Poi c'è una funzione che li mette in questa lista e da questa li controllo. Funziona tutto tranne la parte che non capivo (non sapevo) che hai postato tu. grazie mille
 

LucaMs

Expert
Licensed User
Longtime User
mi scrive ' 26 presente 2 volte ' . quel 26 come faccio a prelevare il nome dell'item (valore) della xclv?.
Per questo ti ho consigliato di...
Usando una Map anziché una List potresti associare i valori agli indici degli item:
Avresti una Map contenente sia i valori ripetuti, sia gli indici degli item.
L'errore che ho commesso è che come chiave della Map ho inserito il valore (associato ai tuoi item) e come valore l'indice del ciclo, mentre devi fare il contrario:
Item_Squadra.Put(Item.Value, i)
Item_Squadra.Put(i, Item.Value)
 

LucaMs

Expert
Licensed User
Longtime User
perché non curi la cosa a livello di database esterno con la sintassi MySQL, con un "SELECT count" ad esempio?
P.s. per quanto riguardo perchè non uso la query di selezione è perchè i dati del DB mi servono tutti.
Immagino che ti servano tutti nel DB, non nella CLV, per cui creare una query apposita, per riempire la CLV sarebbe la giusta soluzione.
 

LucaMs

Expert
Licensed User
Longtime User
Uhm... meglio ancora della Map (fermo restando che usare una query sarebbe la cosa più "giusta") sarebbe usare un custom type.
Es.
B4X:
Type tDuplicato(Value As Int, ItemIndex As Int)

B4X:
Dim lstDuplicati As List
lstDuplicati.Initialize

For i = 0 To Clv_Item_Squadra.Size - 1
    Dim Item As CLVItem = Clv_Item_Squadra.GetRawListItem(i)
    Dim Duplicato As tDuplicato
    Duplicato.Initialize
    Duplicato.Value = Item.Value
    Duplicato.ItemIndex = i
    lstDuplicati.Add(Duplicato)
Next
In questo modo potresti anche ordinare la lista in base a Value o ItemIndex:
B4X:
lstDuplicati.SortType("Value", True)
' oppure
lstDuplicati.SortType("ItemIndex", True)
 
Last edited:

udg

Expert
Licensed User
Longtime User
avvisare (anche per ora con un log) se nella lista esiste un nome
uguale ad un'altro già inserito nella lista.
Non mi è chiaro se:
- vuoi evitare dei duplicati nella lista finale (Item_Squadra?)
- vuoi elencare solo i duplicati
- vuoi elencare solo i duplicati ma con il numero di ricorrenze di ciascuno
Le soluzioni dei post precedenti sono tutte valide, ma la scelta dell'una o dell'altra dipende dallo scopo finale.
Per di più, se non capisco male, i tuoi dati viaggiano da DB a xCLV e da questa a lista Item_Squadra. Magari si può intervenire prima per contare o scartare elementi..
 

XorAndOr

Active Member
Licensed User
Longtime User
Grazie a tutti dell'aiuto.
Innanzitutto ho risolto col codice LucaMs/Elric (e li ringrazio).
Visto che col mio post lascio un po' di dubbi (e ci sono) sul metodo che uso, ma non sono molto bravo in questo.
Praticamente faccio una lettura di tutti i record del database sul server.
Questi dati o valori esempio: (Marco) (Fabio) (Andrea) (Maikol) ecc.. vanno su una XCLV1
Da questa XCLV1 scelgo il nome e lo inserisco in un'altra XCLV2
Qui non posso piu' usare la query del database perchè i dati adesso sono sulla XCLV1 che io devo cliccare per selezionare.
Ora dovrei impedire di inserire 2 nomi uguali in XCLV2.
Oppure verificare se ci sono doppioni.
Dentro la XCLV2 ho anche un button (elimina) se nel caso uno volesse cancellare l'inserimento errato.
Come dite voi potrei agire prima di inserire il valore nell' XCLV2 , e non fare un controllo dopo e eliminare il valore.
Per adesso lascio il codice che mi avete postato in attesa di una migliore soluzione
Grazie raga
 

LucaMs

Expert
Licensed User
Longtime User
Praticamente faccio una lettura di tutti i record del database sul server.
Questi dati o valori esempio: (Marco) (Fabio) (Andrea) (Maikol) ecc.. vanno su una XCLV1
Da questa XCLV1 scelgo il nome e lo inserisco in un'altra XCLV2
Qui non posso piu' usare la query del database perchè i dati adesso sono sulla XCLV1 che io devo cliccare per selezionare.
E non puoi usare la clausola Distinct nella query che carica i dati per la XCLV1? In questa CLV devi poter avere nomi duplicati?
 

XorAndOr

Active Member
Licensed User
Longtime User
E non puoi usare la clausola Distinct nella query che carica i dati per la XCLV1? In questa CLV devi poter avere nomi duplicati?
Fino alla xclv1 è tutto corretto, cioè ho i dati dal database anche con nomi duplicati.
Scegliendo dalla xclv1 ad esempio Marco, gli clicco sul nome e lo aggiungo alla xclv2
Poi scelgo Fabio e lo aggiungo alla xclv2 e così via...
Poi se per qualsiasi motivo scorrendo la xclv1 aggiungo Marco per la seconda volta allaxclv2
vorrei fare un avviso MsgBox che si sta tentando di aggiungere una nome che è già nella lista xclv2
Dovrei correggere il titolo al post, io pensavo di fare un controllo del doppione ma (dopo) l'inserimento errato.
Con i vostri aiuti forse devo fare qualcosa (prima) dell'inserimento in xclv2
Tutto qua.
 

Xfood

Expert
Licensed User
Io utilizzerei un trucchetto , suggerito da @LucaMs creo una mappa , e ogni volta che clicco sulla clv1 prima di aggiungere alla clv2 faccio un if mappa.GetDefault(mario,"non_esiste")="non_esiste" then aggiungo
E mentre aggiungi popoli anche la mappa
 

LucaMs

Expert
Licensed User
Longtime User
Io utilizzerei un trucchetto , suggerito da @LucaMs creo una mappa , e ogni volta che clicco sulla clv1 prima di aggiungere alla clv2 faccio un if mappa.GetDefault(mario,"non_esiste")="non_esiste" then aggiungo
E mentre aggiungi popoli anche la mappa
Stavo per scrivere una cosa simile.

Fatto in quel modo va bene una List.
B4X:
If lstInseriti.IndexOf(NomeClickato) = - 1 Then 'non ancora inserito
   lstInseriti.Add(NomeClickato)
   ' qui crei l'item e lo aggiungi alla XCLV2
Else
   'Messaggio
End If
 

Elric

Well-Known Member
Licensed User
Posto che il progetto che stai sviluppando è complesso e quindi non lo hai postato (ci sta) e che non hai fatto neanche la parafrasi dello stesso né indicato se usi B4A, B4J o B4i (o B4XPages), nella mia testa di soluzioni ce ne sono diverse.

Ad esempio:
1. Popoli la CLV1 dal DB remoto, estrai il valore che ti interessa dalla CLV1 in una variabile, crei una query che seleziona/estrae dal db remoto con un filtro basato sulla variabile e inserisci tutto nella CLV2. Lo trovo macchinoso ma potrebbe fare al caso tuo.
2. "Scarichi" tutto il DB remoto in un db locale SQLite e gestisci tutto con SQLite - dalla mia non-fa-testo esperienza è decisamente più veloce che gestire la cosa tramite list o map, perché finché sono 10 item vabbe', ma se iniziano ad essere 100 o 1000 la differenza la senti.
3. Metti da parte le CLV e usi le B4XTable (che, a memoria, credo siano più versatili per fare quello che ho capito ti serva fare, ma qualcuno più esperto di me potrà smentirmi o magari non ho capito che ti serve).

Grazie Elric, ho provato il tuo codice e funziona benissimo. Sarebbe fantastico se potessi prelevare il nome dell'item anche perchè facendo il log (tuo codice)
mi scrive ' 26 presente 2 volte ' . quel 26 come faccio a prelevare il nome dell'item (valore) della xclv?. ma anche con il codice che hai postato sono mooolto avanti grazie.
P.s. per quanto riguardo perchè non uso la query di selezione è perchè i dati del DB mi servono tutti.Poi c'è una funzione che li mette in questa lista e da questa li controllo. Funziona tutto tranne la parte che non capivo (non sapevo) che hai postato tu. grazie mille
Prego. Il perché ti ritrovi "26" invece che "Marco" o "Salernitana" lo puoi sapere solo tu.

Hai provato con
B4X:
Item1.TextItem
invece che con
B4X:
Item1.Value
?
 

XorAndOr

Active Member
Licensed User
Longtime User
né indicato se usi B4A, B4J o B4i (o B4XPages)
Uso B4XPages Android. Progetto complesso. Allegherò un esempio in B4J della parte interessata per avere l'idea del problemino(mio)

Ad esempio:
1. Popoli la CLV1 dal DB remoto, estrai il valore che ti interessa dalla CLV1 in una variabile, crei una query che seleziona/estrae dal db remoto con un filtro basato sulla variabile e inserisci tutto nella CLV2. Lo trovo macchinoso ma potrebbe fare al caso tuo.
Interessante, farò una prova
Il perché ti ritrovi "26" invece che "Marco" o "Salernitana" lo puoi sapere solo tu.
non ho ancora capito, forse è l'id del record del database, indagherò
Hai provato con
B4X:
Item1.TextItem
invece che con
B4X:
Item1.Value
?
TextItem è di tipo Boolean. Infatti mi logga ' False presente 2 volte '
 
Last edited:

Sagenut

Expert
Licensed User
Longtime User
La soluzione te l'aveva già scritta @LucaMs (insieme agli altri)
Vedi se quì la trovi funzionale.
In pratica Pulisco la List dopo che hai inserito tutto nella CLV1 (immagino che poi l'inserimento sarà fatto tramite lettura da DB e quindi ora sia un Accessorio).
Dopodichè inizio a ripopolare la List insieme alla CLV2 per poter verificare se il nome è già presente.
Se invece non ho capito una mazza............... allora mi scuso.
 

Attachments

  • Test_CLV_NODOPPIONI.zip
    6.3 KB · Views: 107
Last edited:

XorAndOr

Active Member
Licensed User
Longtime User
La soluzione te l'aveva già scritta @LucaMs (insieme agli altri)
Vedi se quì la trovi funzionale.
In pratica Pulisco la List dopo che hai inserito tutto nella CLV1 (immagino che poi l'inserimento sarà fatto tramite lettura da DB e quindi ora sia un Accessorio).
Dopodichè inizio a ripopolare la List insieme alla CLV2 per poter verificare se il nome è già presente.
Se invece non ho capito una mazza............... allora mi scuso.
Grazie Sagenut
Si è la soluzione che cercavo e che non riuscivo a capire come fare.
Mi rimane solo adattarla al mio progetto Android

Grazie a tutti per l'aiuto, a presto
p.s. ero io che non capivo una maz...;)
 
Top