sirve - Cuente el número de ocurrencias de un carácter en una cadena en Javascript
substring javascript (28)
Necesito contar el número de apariciones de un carácter en una cadena.
Por ejemplo, supongamos que mi cadena contiene:
var mainStr = "str1,str2,str3,str4";
Quiero encontrar el recuento de coma ,
carácter, que es 3. Y el recuento de cadenas individuales después de la división a lo largo de coma, que es 4.
También necesito validar que cada una de las cadenas, es decir, str1 o str2 o str3 o str4, no debe exceder, digamos, 15 caracteres.
¿Qué pasa con string.split (desiredCharecter) .length-1
Ejemplo:
var str = "hellow como es la vida"; var len = str.split ("h"). length-1; dará cuenta 2 para el carácter "h" en la cadena anterior;
Acabo de hacer una prueba muy rápida y sucia en repl.it utilizando Node v7.4. Para un solo carácter, el estándar para bucle es el más rápido:
Algún código :
// winner!
function charCount1(s, c) {
let count = 0;
c = c.charAt(0); // we save some time here
for(let i = 0; i < s.length; ++i) {
if(c === s.charAt(i)) {
++count;
}
}
return count;
}
function charCount2(s, c) {
return (s.match(new RegExp(c[0], ''g'')) || []).length;
}
function charCount3(s, c) {
let count = 0;
for(ch of s) {
if(c === ch) {
++count;
}
}
return count;
}
function perfIt() {
const s = ''Hello, World!'';
const c = ''o'';
console.time(''charCount1'');
for(let i = 0; i < 10000; i++) {
charCount1(s, c);
}
console.timeEnd(''charCount1'');
console.time(''charCount2'');
for(let i = 0; i < 10000; i++) {
charCount2(s, c);
}
console.timeEnd(''charCount2'');
console.time(''charCount3'');
for(let i = 0; i < 10000; i++) {
charCount2(s, c);
}
console.timeEnd(''charCount3'');
}
Resultados de unas pocas carreras :
perfIt()
charCount1: 3.843ms
charCount2: 11.614ms
charCount3: 11.470ms
=> undefined
perfIt()
charCount1: 3.006ms
charCount2: 8.193ms
charCount3: 7.941ms
=> undefined
perfIt()
charCount1: 2.539ms
charCount2: 7.496ms
charCount3: 7.601ms
=> undefined
perfIt()
charCount1: 2.654ms
charCount2: 7.540ms
charCount3: 7.424ms
=> undefined
perfIt()
charCount1: 2.950ms
charCount2: 9.445ms
charCount3: 8.589ms
Agregue esta función al prototipo de picadura:
String.prototype.count=function(c) {
var result = 0, i = 0;
for(i;i<this.length;i++)if(this[i]==c)result++;
return result;
};
uso:
console.log("strings".count("s")); //2
Aquí hay una solución similar, pero usa reducir
function countCharacters(char, string) {
return string.split('''').reduce((acc, ch) => ch === char ? acc + 1: acc, 0)
}
Como se mencionó, dividir mucho más rápido que reemplazar.
Aquí hay uno casi tan rápido como los métodos de división y reemplazo, que son un poco más rápidos que el método de expresiones regulares (en cromo).
var num = 0;
for (ch of "str1,str2,str3,str4")
{
if (ch === '','') num++;
}
Creo que encontrará que la solución a continuación es muy corta, muy rápida, capaz de trabajar con cadenas muy largas, capaz de admitir búsquedas de múltiples caracteres, prueba de errores y capaz de manejar búsquedas de cadenas vacías.
function substring_count(source_str, search_str, index) {
source_str += "", search_str += "";
var count = -1, index_inc = Math.max(search_str.length, 1);
index = (+index || 0) - index_inc;
do {
++count;
index = source_str.indexOf(search_str, index + index_inc);
} while (~index);
return count;
}
Ejemplo de uso:
console.log(substring_count("Lorem ipsum dolar un sit amet.", "m "))
function substring_count(source_str, search_str, index) {
source_str += "", search_str += "";
var count = -1, index_inc = Math.max(search_str.length, 1);
index = (+index || 0) - index_inc;
do {
++count;
index = source_str.indexOf(search_str, index + index_inc);
} while (~index);
return count;
}
El código anterior corrige el error de rendimiento principal en Jakub Wawszczyk que el código sigue buscando para buscar una coincidencia incluso después de que indexOf diga que no hay ninguno y su versión en sí misma no funciona porque olvidó dar los parámetros de entrada de la función.
Descubrí que el mejor método para buscar un carácter en una cadena muy grande (que tiene una longitud de 1 000 000 caracteres, por ejemplo) es utilizar el método replace()
.
window.count_replace = function (str, schar) {
return str.length - str.replace(RegExp(schar), '''').length;
};
Puede ver otra suite JSPerf para probar este método junto con otros métodos para encontrar un carácter en una cadena.
El quinto método en la respuesta de Leo Sauers falla, si el personaje está en el principio de la cadena. p.ej
var needle =''A'',
haystack = ''AbcAbcAbc'';
haystack.split('''').map( function(e,i){ if(e === needle) return i;} )
.filter(Boolean).length;
dará 2 en lugar de 3, porque la función de filtro Boolean da false para 0.
Otra posible función de filtro:
haystack.split('''').map(function (e, i) {
if (e === needle) return i;
}).filter(function (item) {
return !isNaN(item);
}).length;
Estaba trabajando en un pequeño proyecto que requería un contador de subcadena. La búsqueda de las frases incorrectas no me proporcionó ningún resultado; sin embargo, después de escribir mi propia implementación, me topé con esta pregunta. De todos modos, este es mi camino, probablemente sea más lento que la mayoría aquí, pero podría ser útil para alguien:
function count_letters() {
var counter = 0;
for (var i = 0; i < input.length; i++) {
var index_of_sub = input.indexOf(input_letter, i);
if (index_of_sub > -1) {
counter++;
i = index_of_sub;
}
}
¡Por favor, avíseme si encuentra que esta implementación falla o no sigue algunos estándares! :)
ACTUALIZACIÓN Es posible que desee sustituir:
for (var i = 0; i < input.length; i++) {
Con:
for (var i = 0, input_length = input.length; i < input_length; i++) {
Lectura interesante que discute lo anterior: http://www.erichynds.com/blog/javascript-length-property-is-a-stored-value
Estoy usando Node.js v.6.0.0 y el más rápido es el que tiene índice (el tercer método en la respuesta de Lo Sauer).
El segundo es:
function count(s, c) {
var n = 0;
for (let x of s) {
if (x == c)
n++;
}
return n;
}
Hay al menos cuatro formas. La mejor opción, que también debería ser la más rápida (debido al motor RegEx nativo), se ubica en la parte superior. jsperf.com actualmente no funciona, de lo contrario, le proporcionaría estadísticas de rendimiento.
Actualización : Por favor, encuentre las pruebas de rendimiento here , y ejecútelas, para contribuir con sus resultados de rendimiento. Los detalles de los resultados se darán más adelante.
1.
("this is foo bar".match(/o/g)||[]).length
//>2
2.
"this is foo bar".split("o").length-1
//>2
No se recomienda dividir. Recurso hambriento. Asigna nuevas instancias de ''Array'' para cada coincidencia. No intentes eso con un archivo de> 100 MB a través de FileReader. En realidad, puede observar fácilmente el uso EXACTO del recurso utilizando la opción de generador de perfiles de Chrome .
3.
var stringsearch = "o"
,str = "this is foo bar";
for(var count=-1,index=-2; index != -1; count++,index=str.indexOf(stringsearch,index+1) );
//>count:2
4.
buscando un solo personaje
var stringsearch = "o"
,str = "this is foo bar";
for(var i=count=0; i<str.length; count+=+(stringsearch===str[i++]));
//>count:2
Actualizar:
5.
mapeo y filtrado de elementos, no se recomienda debido a su ubicación previa de recursos en lugar de usar ''generadores'' de Pythonian
var str = "this is foo bar"
str.split('''').map( function(e,i){ if(e === ''o'') return i;} )
.filter(Boolean)
//>[9, 10]
[9, 10].length
//>2
Compartir: Hice esta gist , con actualmente 8 métodos de conteo de caracteres, para que podamos compartir y compartir nuestras ideas directamente, solo por diversión, y quizás algunos puntos de referencia interesantes :)
He actualizado esta respuesta. Me gusta la idea de usar un partido mejor, pero es más lento:
console.log(("str1,str2,str3,str4".match(/,/g) || []).length); //logs 3
console.log(("str1,str2,str3,str4".match(new RegExp("str", "g")) || []).length); //logs 4
Use un literal de expresión regular si sabe lo que está buscando de antemano, si no puede usar el constructor RegExp
y pase el indicador g
como argumento.
match
devuelve null
sin resultados, por lo que el || []
|| []
La respuesta original que hice en 2009 está abajo. Crea una matriz innecesariamente, pero usar una división es más rápido (a partir de septiembre de 2014). Soy ambivalente, si realmente necesitara la velocidad, no habría duda de que usaría una división, pero preferiría usar el emparejamiento.
Vieja respuesta (desde 2009):
Si buscas las comas:
(mainStr.split(",").length - 1) //3
Si estas buscando el str
(mainStr.split("str").length - 1) //4
Tanto en la respuesta de @Lo como en mi propia división tonta de pruebas de jsperf se avanza en velocidad, al menos en Chrome, pero crear de nuevo la matriz adicional no parece sano.
Hice una leve mejora en la respuesta aceptada, me permite verificar con la coincidencia entre mayúsculas y minúsculas y es un método adjunto al objeto de cadena:
String.prototype.count = function(lit, cis) {
var m = this.toString().match(new RegExp(lit, ((cis) ? "gi" : "g")));
return (m != null) ? m.length : 0;
}
lit
es la cadena a buscar (como ''ex''), y cis es insensibilidad a mayúsculas y minúsculas, por defecto es falso, permitirá la elección de coincidencias que no distinguen entre mayúsculas y minúsculas.
''I love .com''
para la letra minúscula ''o''
, debe utilizar: var amount_of_os = ''I love .com''.count(''o'');
amount_of_os
sería igual a 2
.
var amount_of_os = ''I love .com''.count(''o'', true);
Esta vez, amount_of_os
sería igual a 3
, ya que el capital O
de la cadena se incluye en la búsqueda.
La forma más fácil que descubrí ...
Ejemplo-
str = ''mississippi'';
function find_occurences(str, char_to_count){
return str.split(char_to_count).length - 1;
}
find_occurences(str, ''i'') //outputs 4
Lo siguiente usa una expresión regular para probar la longitud. testex le garantiza que no tiene 16 o más caracteres consecutivos sin comas. Si pasa la prueba, entonces procede a dividir la cadena. contar las comas es tan simple como contar las fichas menos una.
var mainStr = "str1,str2,str3,str4";
var testregex = /([^,]{16,})/g;
if (testregex.test(mainStr)) {
alert("values must be separated by commas and each may not exceed 15 characters");
} else {
var strs = mainStr.split('','');
alert("mainStr contains " + strs.length + " substrings separated by commas.");
alert("mainStr contains " + (strs.length-1) + " commas.");
}
Mi solución:
function countOcurrences(str, value){
var regExp = new RegExp(value, "gi");
return str.match(regExp) ? str.match(regExp).length : 0;
}
Rendimiento de Split vs RegExp
var i = 0;
var split_start = new Date().getTime();
while (i < 30000) {
"1234,453,123,324".split(",").length -1;
i++;
}
var split_end = new Date().getTime();
var split_time = split_end - split_start;
i= 0;
var reg_start = new Date().getTime();
while (i < 30000) {
("1234,453,123,324".match(/,/g) || []).length;
i++;
}
var reg_end = new Date().getTime();
var reg_time = reg_end - reg_start;
alert (''Split Execution time: '' + split_time + "/n" + ''RegExp Execution time: '' + reg_time + "/n");
Sé que esta podría ser una pregunta antigua, pero tengo una solución simple para principiantes de bajo nivel en JavaScript.
Como principiante, solo pude entender algunas de las soluciones a esta pregunta, así que usé dos bucles FOR anidados para verificar cada carácter contra cada otro carácter en la cadena, incrementando una variable de conteo para cada carácter encontrado que sea igual a ese carácter.
Creé un nuevo objeto en blanco donde cada clave de propiedad es un carácter y el valor es cuántas veces apareció cada carácter en la cadena (conteo).
Función de ejemplo: -
function countAllCharacters(str) {
var obj = {};
if(str.length!==0){
for(i=0;i<str.length;i++){
var count = 0;
for(j=0;j<str.length;j++){
if(str[i] === str[j]){
count++;
}
}
if(!obj.hasOwnProperty(str[i])){
obj[str[i]] = count;
}
}
}
return obj;
}
Si está utilizando lodash, el método _.countBy hará esto:
_.countBy("abcda")[''a''] //2
Este método también funciona con array:
_.countBy([''ab'', ''cd'', ''ab''])[''ab''] //2
Simplemente, use la división para averiguar el número de ocurrencias de un carácter en una cadena.
mainStr.split('','').length
// da 4, que es el número de cadenas después de dividir usando una coma delimitadora
mainStr.split('','').length - 1
// da 3, que es el recuento de coma
También puede rest su cadena y trabajar con ella como una matriz de elementos usando
const mainStr = ''str1,str2,str3,str4'';
const commas = [...mainStr].filter(l => l === '','').length;
console.log(commas);
O
const mainStr = ''str1,str2,str3,str4'';
const commas = [...mainStr].reduce((a, c) => c === '','' ? ++a : a, 0);
console.log(commas);
Una búsqueda rápida en Google consiguió esto (de http://www.codecodex.com/wiki/index.php?title=Count_the_number_of_occurrences_of_a_specific_character_in_a_string#JavaScript )
String.prototype.count=function(s1) {
return (this.length - this.replace(new RegExp(s1,"g"), '''').length) / s1.length;
}
Úsalo así:
test = ''one,two,three,four''
commas = test.count('','') // returns 3
Y ahí está:
function character_count(string, char, ptr = 0, count = 0) {
while (ptr = string.indexOf(char, ptr) + 1) {count ++}
return count
}
¡Trabaja con enteros también!
ok, otro con regexp - probablemente no rápido, pero corto y mejor legible que otros, en mi caso solo ''_''
para contar
key.replace(/[^_]/g,'''').length
simplemente elimine todo lo que no se parece a su personaje, pero no se ve bien con una cadena como entrada
El método más rápido parece ser a través del operador de índice:
function charOccurances (str, char)
{
for (var c = 0, i = 0, len = str.length; i < len; ++i)
{
if (str[i] == char)
{
++c;
}
}
return c;
}
Uso:
charOccurances(''example/path/script.js'', ''/'') == 2
O como función prototipo:
String.prototype.charOccurances = function (char)
{
for (var c = 0, i = 0, len = this.length; i < len; ++i)
{
if (this[i] == char)
{
++c;
}
}
return c;
}
Uso:
charOccurances(''example/path/script.js'', ''/'') == 2
var i = 0;
var split_start = new Date().getTime();
while (i < 30000) {
"1234,453,123,324".split(",").length -1;
i++;
}
var split_end = new Date().getTime();
var split_time = split_end - split_start;
i= 0;
var reg_start = new Date().getTime();
while (i < 30000) {
("1234,453,123,324".match(/,/g) || []).length;
i++;
}
var reg_end = new Date().getTime();
var reg_time = reg_end - reg_start;
alert (''Split Execution time: '' + split_time + "/n" + ''RegExp Execution time: '' + reg_time + "/n");
s = ''dir/dir/dir/dir/''
for(i=l=0;i<s.length;i++)
if(s[i] == ''/'')
l++
var a = "acvbasbb";
var b= {};
for (let i=0;i<a.length;i++){
if((a.match(new RegExp(a[i], "g"))).length > 1){
b[a[i]]=(a.match(new RegExp(a[i], "g"))).length;
}
}
console.log(b);
En javascript puede usar el código anterior para obtener la aparición de un carácter en una cadena.