Junte strings com um delimitador apenas se as strings não forem nulas ou vazias

118

Parece que deveria ser simples, desculpe se estou perdendo algo aqui, mas estou tentando encontrar uma maneira simples de concatenar apenas strings não nulas ou não vazias.

Tenho vários campos de endereço distintos:

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

Os valores para esses são definidos com base em alguns campos de formulário na página e em algum outro código js.

Quero produzir o endereço completo em a div, delimitado por vírgula + espaço, algo assim:

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

O problema é que um ou todos esses campos podem ser nulos / vazios.

Existe alguma maneira simples de juntar todos os campos não vazios neste grupo de campos, sem fazer uma verificação do comprimento de cada um individualmente antes de adicioná-lo à string?

Froadie
fonte
Por que não ter todos esses campos em um objeto e fazer um loop, comparar, descartar?
elclanrs

Respostas:

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 é o mesmo que .filter(x => x)) remove todos os valores "falsos" (nulos, indefinidos, strings vazias, etc.). Se a sua definição de "vazio" for diferente, você terá que fornecê-la, por exemplo:

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

irá manter apenas strings não vazias na lista.

-

(resposta obsoleta do jquery)

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

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

Mais uma solução de uma linha, que não requer jQuery:

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

text = [address, city, state, zip].filter(function (val) {return val;}).join(', ');
aga
fonte
40
Esta é provavelmente a melhor resposta. Usa funções nativas. Se você estiver usando es6 / es2015, pode ser reduzido para apenas [address, city, state, zip].filter(val => val).join(', ')
Sir.Nathan Stassen,
14

Solução Lodash :_.filter([address, city, state, zip]).join()

Tim Santeford
fonte
13

Somente:

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

A solução de @aga é ótima, mas não funciona em navegadores mais antigos como o IE8 devido à falta de Array.prototype.filter () em seus mecanismos JavaScript.

Para aqueles que estão interessados ​​em uma solução eficiente trabalhando em uma ampla gama de navegadores (incluindo IE 5.5 - 8) e que não requer jQuery , veja abaixo:

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);
};

Inclui algumas otimizações de desempenho descritas no MDN aqui .

E aqui está um exemplo de uso:

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

Experimentar

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

Demo: Fiddle

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