Unir cadenas con un delimitador solo si las cadenas no son nulas o vacías

118

Parece que debería ser simple, lo siento si me falta algo aquí, pero estoy tratando de encontrar una forma simple de concatenar solo cadenas no nulas o no vacías.

Tengo varios campos de dirección distintos:

var address;
var city;
var state;
var zip;

Los valores para estos se establecen en función de algunos campos de formulario en la página y algún otro código js.

Quiero generar la dirección completa en a div, delimitada por coma + espacio, algo como esto:

$("#addressDiv").append(address + ", " + city + ", " + state + ", " + zip);

El problema es que uno o todos estos campos podrían ser nulos o estar vacíos.

¿Existe alguna forma sencilla de unir todos los campos no vacíos en este grupo de campos, sin hacer una verificación de la longitud de cada uno individualmente antes de agregarlo a la cadena?

froadie
fuente
¿Por qué no tener todos esos campos en un objeto y luego repetir, comparar y descartar?
elclanrs

Respuestas:

218

Considerar

var address = "foo";
var city;
var state = "bar";
var zip;

text = [address, city, state, zip].filter(Boolean).join(", ");
console.log(text)

.filter(Boolean)(que es lo mismo que .filter(x => x)) elimina todos los valores "falsos" (nulos, indefinidos, cadenas vacías, etc.). Si su definición de "vacío" es diferente, deberá proporcionarla, por ejemplo:

 [...].filter(x => typeof x === 'string' && x.length > 0)

solo mantendrá las cadenas no vacías en la lista.

-

(respuesta de jquery obsoleta)

var address = "foo";
var city;
var state = "bar";
var zip;

text = $.grep([address, city, state, zip], Boolean).join(", "); // foo, bar
georg
fuente
117

Otra solución de una línea, que no requiere jQuery:

var address = "foo";
var city;
var state = "bar";
var zip;

text = [address, city, state, zip].filter(function (val) {return val;}).join(', ');
aga
fuente
40
Esta es probablemente la mejor respuesta. Utiliza funciones nativas. Si está usando es6 / es2015, puede abreviarlo a [address, city, state, zip].filter(val => val).join(', ')
Sir.Nathan Stassen
14

Solución Lodash :_.filter([address, city, state, zip]).join()

Tim Santeford
fuente
13

Sólo:

[address, city, state, zip].filter(Boolean).join(', ');
tikhpavel
fuente
5

La solución de @ aga es excelente, pero no funciona en navegadores más antiguos como IE8 debido a la falta de Array.prototype.filter () en sus motores JavaScript.

Para aquellos que estén interesados ​​en una solución eficiente que funcione en una amplia gama de navegadores (incluido IE 5.5 - 8) y que no requiera jQuery , consulte a continuación:

var join = function (separator /*, strings */) {
    // Do not use:
    //      var args = Array.prototype.slice.call(arguments, 1);
    // since it prevents optimizations in JavaScript engines (V8 for example).
    // (See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments)
    // So we construct a new array by iterating through the arguments object
    var argsLength = arguments.length,
        strings = [];

    // Iterate through the arguments object skipping separator arg
    for (var i = 1, j = 0; i < argsLength; ++i) {
        var arg = arguments[i];

        // Filter undefineds, nulls, empty strings, 0s
        if (arg) {
            strings[j++] = arg;
        }
    }

    return strings.join(separator);
};

Incluye algunas optimizaciones de rendimiento descritas en MDN aquí .

Y aquí hay un ejemplo de uso:

var fullAddress = join(', ', address, city, state, zip);
Alexander Abakumov
fuente
1

Tratar

function joinIfPresent(){
    return $.map(arguments, function(val){
        return val && val.length > 0 ? val : undefined;
    }).join(', ')
}
$("#addressDiv").append(joinIfPresent(address, city, state, zip));

Demostración: violín

Arun P Johny
fuente
0
$.each([address,city,state,zip], 
    function(i,v) { 
        if(v){
             var s = (i>0 ? ", ":"") + v;
             $("#addressDiv").append(s);
        } 
    }
);`
nicb
fuente