-1

I am writing es templates. I want to make the codes as simple as possible and at best avoid using (function(){return XXX})()

The context: When a list has nothing, prints nothing, otherwise prints the list with ul tags around.

${
  // same filter 2 times
  arr.filter( d=>d.prop1=="a" ).length==0
    ? ""
    : `<ul> ${ arr.filter( d=>d.prop1=="a" ).map(d=>`<li>${d.text}</li>`) } </ul>`
}

or

${
  // function makes it bulky
  (function(){
    let arr2 = arr.filter( d=>d.prop1=="a" );
    if( arr2.length == 0 ){
      return ""
    }else{
      return `<ul> ${ arr2.map(d=>`<li>${d.text}</li>`) } </ul>`
    }
  })()
}

one more context, sometimes the problem is like this:

 const NAMES = [
   { name:"John" },
   { name:"Michael", nickname:"Mike" },
 ];

 NAMES.map( n=>`name: ${n.name} ${ n.nickname? "("+n.nickname+")":"" }` ).join("\n")
 // can simplify n.nickname? "("+n.nickname+")":"" ?

Anyone come up with a way to simplify these? Thanks.

John Lok Ho
  • 3
  • 1
  • 2

2 Answers2

0

Using array.some is a bit faster than checking the length of the filtered array.

${
    ARR.some(o => !!o.attr) 
    ? `<ul>${ARR.filter(o => !!o.attr).map(o => (`<li>${o.attr}</li>`))}</ul>` 
    : ""
}

Also, since most templates don't print false value, you can simplify with &&.

${ ARR.some(o => !!o.attr) && `<ul>${ARR.filter(o => !!o.attr).map(o => (`<li>${o.attr}</li>`))}</ul>` }

If you do not want to maintain the duplicated condition, using a variable is necessary, so I don't know any other way rather than using a function. Using the tricks from above, you can reduce the function size a bit.

${
    ((arr) => {
        arr = arr.filter(o => !!o.attr);
        return !!arr.length && `<ul>${arr.map(o => (`<li>${o.attr}</li>`))}</ul>`;
    })(ARR)
}

For NAMES, you can just use backsticks.

NAMES.map(o => (`Name: ${o.name}${o.nickname ? ` (${o.nickname})` : ""}`))
Quan To
  • 697
  • 3
  • 10
  • There is still the filter function part needed to be maintained twice.If there are no more answers, I will mark this as answer. – John Lok Ho Jan 21 '21 at 06:47
  • `filter` runs for the whole array. `some` runs till the first match. There's only one `filter` function called here. The `o => !!o.attr` part is just a condition arrow function for `some` or `filter`. – Quan To Jan 22 '21 at 09:29
  • If you don't want to maintain the duplicated condition, I guess using a function is the only way. Using the tricks from before, you can reduce the size of the function quite a bit. I added an example. – Quan To Jan 22 '21 at 09:40
0

You can assign filter value to object and then apply length in condition part of ?:. Then you can use that object in true part to get map.

Your code will look like below.

(a = arr.filter(d => d.prop1 == "a")).length ? `<ul> ${ a.map(d=>`<li>${d.prop1}</li>`) } </ul>` : "";

Try it below.

function getTemplate(arr) {
  return (a = arr.filter(d => d.prop1 == "a")).length ? `<ul> ${ a.map(d=>`<li>${d.prop1}</li>`) } </ul>` : "";
}

console.log(getTemplate([{prop1: 'a'}])); // output : <ul> <li>a</li> </ul>
console.log(getTemplate([{prop1: 'b'}])); // output :

Similarly with NAMES

  1. Use (n.nickname || "") which will return "" in case of value is null or undefined.
  2. At last replace () with '' so if there is no nickname then it would have () at end and we can remove it with replace.

const NAMES = [{
    name: "John"
  },
  {
    name: "Michael",
    nickname: "Mike"
  },
];

// Use (n.nickname || "") which will return "" in case of value is null or undefined. 
// At last replace () with empty string so if there is no nickname then it would have () at end and we can remove it with replace.
let result = NAMES.map(n => `name: ${n.name} ${"(" + (n.nickname || "") + ")" }`.replace(' ()', '')).join("\n");

console.log(result);
Karan
  • 12,059
  • 3
  • 24
  • 40
  • Thanks! It is OK but I think I do not love to maintain the replacing content. – John Lok Ho Jan 21 '21 at 06:51
  • hmm... the ( tempvar = filter() ) is the neatest code, however, it will not work under "use strict" and tempvar is created as a byproduct. Still, your answer has inspired me, thanks! – John Lok Ho Jan 21 '21 at 10:18