Gavin Hanel
Gavin Hanel

Reputation: 43

Understanding how reduce can be used instead of map and join in this function

I've got the following function that gets all checked checkboxes on my html form with the given element Name. I have a loose understanding that a reduce function can replace the .map and .join sections so was looking for a poke in the right direction of how to implement that and also if there is any other steps I could take to optimise this function?

  function getCheckedValuesOf(elmName){
    return [...document.getElementsByName(elmName)].filter(box=>box.checked==true).map(box=>box.value).join(", ")
  }

Upvotes: 4

Views: 536

Answers (4)

Akshay Bande
Akshay Bande

Reputation: 2587

Can you try this one? Let me know if it works.

function getCheckedValuesOf(elmName) {
    return [...document.getElementsByName(elmName)].reduce((a, b) => b.checked && b.value && (a.length>0 ? `${a}, ${b.value}`: `${a} ${b.value}`) || a, "");
}

Upvotes: 2

Alex L
Alex L

Reputation: 4241

You can do it with reduce only. modified from @akshaybande 's answer to fix the errors (like leading ", " etc.)

function getCheckedValuesOf(elmName) {
    return [...document.getElementsByName(elmName)].reduce((acc, cur) => {
      if (cur.checked && cur.value){
          return acc.length >= 1 ? `${acc}, ${cur.value}` : `${cur.value}`
      } 
      return acc;
    }, "");
}

document.getElementById("log").onclick = () => console.log(getCheckedValuesOf("name"))
console.log(getCheckedValuesOf("name"))
<input type="checkbox" name="name" checked="false" value="1"/>1
<input type="checkbox" name="name" value="2"/>2
<input type="checkbox" name="name" value="3"/>3
<input type="checkbox" name="name" value="4"/>4
<input type="checkbox" name="name" checked="false" value="5"/>5
<input type="checkbox" name="name" value="6"/>6

<button id="log">log</button>

Upvotes: 1

jonatjano
jonatjano

Reputation: 3738

function getCheckedValuesOf(elmName) {
  return [...document.getElementsByName(elmName)]
    // acc is value returned by previous iteration
    // curr is the current iterated element
    .reduce((acc, curr) => {
      // do nothing on unchecked
      if (curr.checked) {
        // add a , only if acc is not empty, to prevent useless starting ,
        acc += (acc !== "" ? ", " : "") + curr.value
      }
      
      // always return acc, or next iteration will have acc === undefined
      return acc;
      
    // second argument of reduce is the initial value of acc
    // if not set then it default to the first element of the array
    // and the iteration starts on the second element
    }, '')
}

document.getElementById("log").onclick = () => console.log(getCheckedValuesOf("name"))
console.log(getCheckedValuesOf("name"))
<input type="checkbox" name="name" checked="false" value="i1"/>i1
<input type="checkbox" name="name" value="i2"/>i2
<input type="checkbox" name="name" checked="false" value="i3"/>i3
<input type="checkbox" name="name" value="i4"/>i4
<input type="checkbox" name="name" checked="false" value="i5"/>i5
<input type="checkbox" name="name" value="i6"/>i6

<button id="log">log</button>

Upvotes: 4

something like this?

        function getCheckedValuesOf(elmName) {
            return [...document.getElementsByName(elmName)]
                .reduce((str, box) => {
                    if (box.checked == true) {
                        str += box.value +', '
                    }
                    return str;
                }, '');
        }

        document.querySelector('button').onclick = () => {
            console.log(getCheckedValuesOf('input'))
        }
    <input type="checkbox" checked name="input" value="1">
    <input type="checkbox" name="input" value="2">
    <input type="checkbox" name="input" value="3">
    <input type="checkbox" checked name="input" value="4">
    <input type="checkbox" name="input" value="5">
    <button>click</button>

Upvotes: 0

Related Questions