IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Rust Discussion :

[Rust 1.75.0][Linux] Comment trier de manière élégante un objet ReadDir ?


Sujet :

Rust

  1. #1
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut [Rust 1.75.0][Linux] Comment trier de manière élégante un objet ReadDir ?
    Salutations !!

    J'ai un bug dans mon programme, les commentaires n'arrivent pas dans le bon ordre, et ceux-ci sont calqués sur des fichiers lus dans un répertoire.
    Ces fichiers sont lus, contrairement à ce que je pensais, sur base du nom du fichier, et non de la date de création ce qui me pose soucis.

    Du coup, me voilà obligé de trier les entrées DirEntry contenues dans un ReadDir.
    Le soucis c'est qu'il n'y a pas de méthode sort() pour ReadDir :{

    Comment je pourrais faire ?

  2. #2
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    voilà ce que je ne trouve pas élégant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	// Pas beau je trouve
     
    	for fichieratrier in iterator_folder.unwrap()
    	{
    		if fichieratrier.is_ok()
    		{
    			vecteurtri.push(fichieratrier.unwrap());
    		}
    	}
     
    	vecteurtri.sort_by(|gauche,droite|gauche.metadata().unwrap().modified().unwrap().cmp(&droite.metadata().unwrap().modified().unwrap()));

  3. #3
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 562
    Points : 15 493
    Points
    15 493
    Par défaut
    L'idée de créer un vecteur a trier est bonne. Pour avoir un code plus simple tu pourrais :
    • utiliser directement les méthodes filter_map() et collect() de l’itérateur plutôt que de faire une boucle pour recréer un vecteur.
    • utiliser sort_by_key() plutôt que sort_by() pour simplifier la comparaison
    • utiliser l'opérateur ? plutôt que des unwrap() (pas possible dans la closure malheureusement)


    Ca donnerait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        let mut dirs = iterator_folder?
            .filter_map(|f| f.ok())   // ne garde que les resultats Ok et extrait leur contenu
            .collect::<Vec<_>>();     // convertit en Vec
        dirs.sort_by_key(|i| i.metadata().unwrap().modified().unwrap());

  4. #4
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Oui !! Wow !!
    Merci !!

  5. #5
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Bonjour,

    Citation Envoyé par Uther Voir le message
    utiliser l'opérateur ? plutôt que des unwrap() (pas possible dans la closure malheureusement)
    […]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        let mut dirs = iterator_folder?
            .filter_map(|f| f.ok())   // ne garde que les resultats Ok et extrait leur contenu
            .collect::<Vec<_>>();     // convertit en Vec
        dirs.sort_by_key(|i| i.metadata().unwrap().modified().unwrap());
    Pour compléter la réponse d'Uther, pour éviter les .unwrap(), on peut faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    use std::fs::{self, DirEntry, Metadata};
    use std::io;
    use std::path::Path;
    use std::time::SystemTime;
     
    #[allow(unused)]
    #[derive(Debug)]
    struct ExtendedDirEntry {
        entry: DirEntry,
        metadata: Metadata,
        modified: SystemTime,
    }
     
    fn read_dir_and_sort_by_modified(path: &Path) -> io::Result<Vec<ExtendedDirEntry>> {
        let mut result = fs::read_dir(path)?
            .map(|entry| {
                let entry = entry?;
                let metadata = entry.metadata()?;
                let modified = metadata.modified()?;
                Ok(ExtendedDirEntry {
                    entry,
                    metadata,
                    modified,
                })
            })
            .collect::<io::Result<Vec<ExtendedDirEntry>>>()?;
        result.sort_by_key(|x| x.modified);
        Ok(result)
    }
     
    fn main() -> io::Result<()> {
        let extended_entries = read_dir_and_sort_by_modified(".".as_ref())?;
        for extended_entry in &extended_entries {
            println!("- {extended_entry:?}");
        }
        Ok(())
    }
    Remarques :

    • Mon code a un comportement différent : si un io::Result<DirEntry> est un Err au lieu d'un Ok, je remonte l'erreur au lieu de l'ignorer. Si on veut vraiment l'ignorer, alors on peut remplacer .map(|entry| { let entry = entry?; par .filter_map(Result::ok).map(|entry| {, mais pourquoi ignorer l'erreur ?
    • Dans mon code, pour simplifier, on peut retirer le champ metadata de la structure ExtendedDirEntry. Par contre, si le vrai code a encore besoin des métadonnées plus tard, alors il vaut mieux laisser metadata dans ExtendedDirEntry que d'appeler à nouveau std::fs::DirEntry::metadata.

  6. #6
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Oui, merci encore, c'est beau ^^ c'est vraiment magnifique ^^
    Euh...c'est pas demain que je vais réellement appréhender la puissance de Rust, en matière d'orienté objet c'est vraiment au-dessus de tout...

  7. #7
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    J'ai pas mal de bouquins que je lis et j'essaye de capter avec des projets persos qui, pour le moment, consistent à prendre des programmes écrits en C et les "porter" en Rust.

    Là j'ai du mal avec les traits, les closures (bien qu'en perl il y en aie mais je sais pourquoi ça "passe" mieux en perl), en OO j'aime le polymorphisme des fonctions (C++, Java, ...) et là en Rust j'ai vraiment du mal.
    Bon, ça fait quelques mois que je "chipottes" mais j'ai du chemin à faire là... c'est pas un réflexe ^^

Discussions similaires

  1. [Linux] comment installer GLUT
    Par Mathieu.J dans le forum GLUT
    Réponses: 5
    Dernier message: 28/09/2012, 17h39
  2. [oracle9i-Linux] Comment vider un UNDO tablespace
    Par Loïck dans le forum Oracle
    Réponses: 8
    Dernier message: 03/12/2009, 13h53
  3. Réponses: 4
    Dernier message: 26/06/2005, 23h28
  4. Comment trier une DBGRID en cliquant sur une colonne
    Par sessime dans le forum Bases de données
    Réponses: 8
    Dernier message: 09/10/2004, 16h18
  5. Paradox 7 Comment trier et marquer données dans une DBgrid
    Par technico dans le forum Bases de données
    Réponses: 12
    Dernier message: 04/07/2004, 11h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo