J'ai, en Java, un arraylist avec ces valeurs (beaucoup de lignes, ceci est juste un extrait)
20/03/2013 23:31:46 6870 6810 6800 6720 6860 6670 6700 6650 6750 6830 34864 34272 20/03/2013 23:31:46 6910 6780 6800 6720 6860 6680 6620 6690 6760 6790 35072 34496
Où les deux premières valeurs sont des chaînes qui contiennent des données et sont stockées dans un seul élément.
Ce que je veux faire, c'est comparer les éléments de données de la chaîne et supprimer, par exemple, le deuxième élément et tous les éléments mentionnés dans cette ligne.
Pour le moment, j'ai utilisé un cycle for pour que tous les 13 éléments comparent la chaîne (afin de comparer uniquement les chaînes de données)
Ma question: puis-je mettre en œuvre d'autres meilleures solutions?
Ceci est mon code:
import Java.util.Scanner;
import Java.util.List;
import Java.util.ArrayList;
import Java.io.*;
import Java.text.SimpleDateFormat;
import Java.util.Date;
public class Downsampler {
public static void main(String[] args) throws Exception{
//The input file
Scanner s = new Scanner(new File("prova.txt"));
//Saving each element of the input file in an arraylist
ArrayList<String> list = new ArrayList<String>();
while (s.hasNext()){
list.add(s.next());
}
s.close();
//Arraylist to save modified values
ArrayList<String> ds = new ArrayList<String>();
//
int i;
for(i=0; i<=list.size()-13; i=i+14){
//combining the first to values to obtain data
String str = list.get(i)+" "+list.get(i+1);
ds.add(str);
//add all the other values to arraylist ds
int j;
for(j=2; j<14; j++){
ds.add(list.get(i+j));
}
//comparing data values
int k;
for(k=0; k<=ds.size()-12; k=k+13){
ds.get(k); //first data string element
//Comparing with other strings and delete
//TODO
}
}
}
}
Créer une liste de valeurs uniques
Vous pouvez utiliser la méthode Set.toArray()
.
Une collection qui ne contient aucun élément en double. Plus formellement, ensembles ne contient aucune paire d'éléments e1 et e2 tels que e1.equals (e2) et at la plupart un élément nul. Comme son nom l'indique, cette interface modélise l'abstraction de l'ensemble mathématique.
Essayez de rechercher les doublons avec une méthode .contains()
sur ArrayList avant d’ajouter un nouvel élément.
Ça ressemblerait à quelque chose comme ça
if(!list.contains(data))
list.add(data);
Cela devrait éviter les doublons dans la liste, et ne pas gâcher l'ordre des éléments , comme les gens semblent chercher.
HashSet hs = new HashSet();
hs.addAll(arrayList);
arrayList.clear();
arrayList.addAll(hs);
//Saving each element of the input file in an arraylist
ArrayList<String> list = new ArrayList<String>();
while (s.hasNext()){
list.add(s.next());
}
//That's all you need
list = (ArrayList) list.stream().distinct().collect(Collectors.toList());
Vous pouvez utiliser un ensemble. C'est une collection qui n'accepte pas les doublons.
Utilisez Set
...
Set<String> list = new HashSet<>();
while (s.hasNext()){
list.add(s.next());
}
...
Vous pouvez facilement le faire avec un Hashmap
. Vous avez évidemment une clé (qui est les données de chaîne) et quelques valeurs.
Bouclez toutes vos lignes et ajoutez-les à votre carte.
Map<String, List<Integer>> map = new HashMap<>();
...
while (s.hasNext()){
String stringData = ...
List<Integer> values = ...
map.put(stringData,values);
}
Notez que dans ce cas, vous conserverez l'occurrence last des lignes dupliquées. Si vous préférez conserver l’occurrence first et supprimer les autres, vous pouvez cocher la case Map.containsKey(String stringData);
avant de placer la carte.
Remplacez simplement la méthode boolean equals () de l'objet personnalisé. Supposons que vous avez une liste de tableaux avec les champs personnalisés f1, f2, ... override
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CustomObject)) return false;
CustomObject object = (CustomObject) o;
if (!f1.equals(object.dob)) return false;
if (!f2.equals(object.fullName)) return false;
...
return true;
}
et vérifiez à l'aide de la méthode ArrayList de la méthode contient (). C'est tout.
Assez tard pour la fête, mais voici mes deux cents:
LinkedHashSet
Je suppose que ce dont vous avez besoin est une collection qui:
LinkedHashSet
fait ceci. L'avantage par rapport à l'utilisation de ArrayList
est que LinkedHashSet
a une complexité de O(1) pour l'opération contains
, par opposition à ArrayList
, qui a O(n).
Bien sûr, vous devez implémenter correctement les méthodes equals
et hashCode
de votre objet.
Vous pouvez lire du fichier à la carte, où la clé est la date et ignorer la ligne entière si la date est déjà dans la carte
Map<String, List<String>> map = new HashMap<String, List<String>>();
int i = 0;
String lastData = null;
while (s.hasNext()) {
String str = s.next();
if (i % 13 == 0) {
if (map.containsKey(str)) {
//skip the whole row
lastData = null;
} else {
lastData = str;
map.put(lastData, new ArrayList<String>());
}
} else if (lastData != null) {
map.get(lastData).add(str);
}
i++;
}
Si vous avez besoin de valeurs uniques, vous devez utiliser l'implémentation de l'interface SET
.
J'utilise la classe d'assistance. Pas sûr que ce soit bon ou mauvais
public class ListHelper<T> {
private final T[] t;
public ListHelper(T[] t) {
this.t = t;
}
public List<T> unique(List<T> list) {
Set<T> set = new HashSet<>(list);
return Arrays.asList(set.toArray(t));
}
}
Utilisation et test:
import static org.assertj.core.api.Assertions.assertThat;
public class ListHelperTest {
@Test
public void unique() {
List<String> s = Arrays.asList("abc", "cde", "dfg", "abc");
List<String> unique = new ListHelper<>(new String[0]).unique(s);
assertThat(unique).hasSize(3);
}
}
Ou version Java8:
public class ListHelper<T> {
public Function<List<T>, List<T>> unique() {
return l -> l.stream().distinct().collect(Collectors.toList());
}
}
public class ListHelperTest {
@Test
public void unique() {
List<String> s = Arrays.asList("abc", "cde", "dfg", "abc");
assertThat(new ListHelper<String>().unique().apply(s)).hasSize(3);
}
}