Je reçois une liste de fichiers dans un objet et j'ai juste besoin d'afficher un nom de fichier et son type dans une table.
Tous les fichiers reviennent d'un serveur au format suivant: timestamp_id_filename .
Exemple: 1568223848_12345678_some_document.pdf
J'ai écrit une fonction d'assistance qui coupe le string.
Au début, je l'ai fait avec la méthode String.prototype.split () , j'ai utilisé regex, mais là encore - il y avait un problème. Les fichiers peuvent avoir des traits de soulignement dans leurs noms, ce qui n'a pas fonctionné, donc j'avais besoin de quelque chose d'autre. Je ne pouvais pas trouver une meilleure idée. Je pense que ça a l'air vraiment stupide et ça m'a hanté toute la journée.
La fonction ressemble à ceci:
const shortenString = (attachmentName) => {
const file = attachmentName
.slice(attachmentName.indexOf('_') + 1)
.slice(attachmentName.slice(attachmentName.indexOf('_') + 1).indexOf('_') + 1);
const fileName = file.slice(0, file.lastIndexOf('.'));
const fileType = file.slice(file.lastIndexOf('.'));
return [fileName, fileType];
};
Je me demande s'il y en a plus manière élégante de résoudre le problème sans utiliser de boucles.
8 Réponses :
Vous pouvez un peu enchaîner .indexOf pour obtenir le deuxième offset et tout autre, bien que plus de deux paraissent moche. La raison en est que indexOf prend l'index de départ comme deuxième argument, donc passer l'index de la première occurrence vous aidera à trouver la seconde:
var [,number1, number2, filename, extension] = /([0-9]+)_([0-9]+)_(.*?)\.([0-9a-z]+)/i.exec(name) // Prints: "1568223848 12345678 some_document pdf" console.log(number1, number2, filename, extension);
Ma solution serait donc :
var index = name.indexOf("_",name.indexOf("_")+1));
var [timestamp, name] = [name.substring(0, index), name.substr(index+1)];
Alternativement, en utilisant une expression régulière:
var secondUnderscoreIndex = name.indexOf("_",name.indexOf("_")+1);
Vous pouvez utiliser replace et split , avec le modèle que nous remplaçons la chaîne jusqu'au deuxième _ à partir du début de la chaîne et que nous diviser sur . pour obtenir le nom et le type
let nameAndType = (str) => {
let replaced = str.replace(/^(?:[^_]*_){2}/g, '')
let splited = replaced.split('.')
let type = splited.pop()
let name = splited.join('.')
return {name,type}
}
console.log(nameAndType("1568223848_12345678_some_document.pdf"))
console.log(nameAndType("1568223848_12345678_some_document.xyz.pdf"))
Cela fonctionne et est la réponse la plus élégante à ce jour, mais si le nom du fichier comporte des points, il divise la chaîne en plusieurs éléments: <
@Bart ouais point valide terminé, maintenant il gérera également ce cas
Divisez la chaîne de nom de fichier en un tableau sur des traits de soulignement. Supprimez les deux premiers éléments du tableau. Rejoignez le reste du tableau avec des traits de soulignement. Vous avez maintenant le nom de votre fichier.
J'aime la simplicité ...
Si jamais vous avez besoin de la date dans les temps, ils sont dans [1] et [2
var getFilename = function(str) {
return str.match(/(\d+)_(\d+)_(.*)/)[3];
}
var f = getFilename("1568223848_12345678_some_document.pdf");
console.log(f)
sur la note latérale: - (\ d +) peut être remplacé par (?: \ d +) et que le la valeur souhaitée peut être référencée comme match (/.../) [1]
function splitString(val){
return val.split('_').slice('2').join('_');
}
function getParts(str) {
const re = /expression/;
...
}
quelques notes:
vous voulez créer l'expression régulière 1 fois. Si vous faites cela
const re = /(.*?)_(.*?)_(.*)/; const name = "1568223848_12345678_some_document.pdf"; [,date, id, filename] = re.exec(name); console.log(date); console.log(id); console.log(filename);
Ensuite, vous créez un nouvel objet d'expression régulière à chaque fois que vous appelez getParts .
. *? est plus rapide que . *
Ceci est dû au fait que . * est gourmand, donc au moment où le moteur d'expression régulière voit qu'il met tout le reste de la chaîne dans cet emplacement, puis vérifie s'il peut continuer l'expression. S'il échoue, il recule d'un personnage. Si cela échoue, il recule un autre caractère, etc .... . *? d'autre part est satisfait dès que possible. Donc il ajoute un caractère puis voit si la partie suivante de l'expression fonctionne, sinon il ajoute un autre caractère et voit si les expressions fonctionnent, etc.
le fractionnement sur '_' fonctionne mais il pourrait potentiellement créer de nombreuses chaînes temporaires
par exemple si le nom du fichier est 1234_1343_a________________________.pdf
vous devrez tester pour voir si l'utilisation d'une experssion régulière est plus rapide ou plus lente que la division, en supposant que la vitesse compte.
Si jamais les noms de fichiers ont ce format timestamp_id_filename. Vous pouvez utiliser une expression régulière qui ignore les deux premiers «_» et enregistre le suivant.
test:
var filename = '1568223848_12345678_some_document.pdf'; console.log(filename.match(/[^_]+_[^_]+_(.*)/)[1]); // result: 'some_document.pdf'
Explication: /[^ +[^ +(.*)/
[^ +: prendre des caractères différents de ' em> ' : prendre le caractère '' Répétez donc deux '_' sont ignorés (. *): Enregistrer les caractères dans un groupe
méthode de correspondance: Retourne le tableau, son premier élément est la capture de l'expression correspondante, les éléments suivants sont des groupes enregistrés.
const getShortString = (str) => str.replace(/^(?:[^_]*_){2}/g, '')
For input like
1568223848_12345678_some_document.pdf, it should give you something like some_document.pdf