1

My target is to create a key and append them in a DIV. My old function works good but I have made adjustments so I changed my code to a better one. The problem is, I cannot append anymore when the array is = 1.

This is my old code: (We can see here after being matched, they're appended to the DIV using keys. Even if length = 1, there's also a key to append on my div).

//just for demo....
var data = {
  "data2": [{
    "entryID": "1",
    "player": "testing1",
    "level": "3"
  }, {
    "entryID": "2",
    "player": "testing2",
    "level": "1"
  }, {
    "entryID": "3",
    "player": "testing3",
    "level": "2"
  }, {
    "entryID": "4",
    "player": "testing4",
    "level": "2"
  }, {
    "entryID": "5",
    "player": "testing5",
    "level": "1"
  }, {
    "entryID": "6",
    "player": "testing6",
    "level": "5"
  }]
}

const combine = (source) => {
  return source.reduce((acc, curr) => {
    if (acc[curr.level]) {
      const levelArr = acc[curr.level];
      const last = levelArr[levelArr.length - 1];
      if (last.length === 2) {
        levelArr.push([curr])
      } else {
        last.push(curr)
      }
    } else {
      acc[curr.level] = [
        [curr]
      ];
    }
    return acc;
  }, {})
};

function removeDuplicates(result) {
  return Object.values(result.reduce((acc, curr) => {
    acc[curr.player] = acc[curr.player] || curr;
    return acc;
  }, {}))
}


result = combine(removeDuplicates(data.data2));
var keys = Object.keys(result)
var html = ""
for (var i = 0; i < keys.length; i++) {
  result[keys[i]].forEach(function(val) {
    var length_ = val.length; //length of the json aray inside obj
    val.forEach(function(value, index) {

      var entryIDs = index == 0 ? "entryIDM[]" : "entryIDW[]"
      var players = index == 0 ? "playerM[]" : "playerW[]"
      var levels = index == 0 ? "levelM[]" : "levelW[]"
      html += `<input type="text" name="${entryIDs}" value="${value.entryID}"> 
                 <input type="text" name="${players}" value="${value.player}">
                 <input type="text" name="${levels}" value="${value.level}">`

      //if length is only one
      if (length_ == 1) {
        //just add inputs with nm..
        html += `<input type="text" name="entryIDW[]" value="nm"> <input type="text" name="playerW[]" value="nm"><input type="text" name="levelW[]" value="nm">`

      }

    })
  })
}
document.getElementById("result").innerHTML = html
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="result"></div>

This is my new codes and i can't append it when the length is = 1 or 2.

const source = [
  {
    entryID: 1,
    entryName: "player1",
    weight: 1900,
  },
  {
    entryID: 2,
    entryName: "player1",
    weight: 1900,
  },
  {
    entryID: 3,
    entryName: "player3",
    weight: 1905,
  },
  {
    entryID: 4,
    entryName: "player4",
    weight: 1905,
  },
  {
    entryID: 5, 
    entryName: "player5",
    weight: 1910,
  },


];

function combine(
  data = [],
  different = 0,
  maxGroupSize = 2,
  sortedStatement = (a, b) => a.weight - b.weight
) {
  const sortedData = [...data].sort(sortedStatement); 

  const dataGroups = sortedData.reduce((acc, item) => {
    const findedAccItem = acc.find(
      (accItem) =>
        accItem.length < maxGroupSize && 
        accItem[0].weight + different >= item.weight && 
        !accItem.find((obj) => obj.entryName === item.entryName ) 
    );
    if (findedAccItem) {
      findedAccItem.push(item);
    } else {
      acc.push([item]);
    }
    return acc;
  }, []);

  const namedDataGroups = dataGroups.reduce((acc, item, index) => {

    const key = [index, ...item.map((item) => item.weight)].join("_");
    acc[key] = item;
    return acc;
  }, {});

  return namedDataGroups;
}


console.log("Example #1: ", combine(source));

My target is to append the keys. Same as the first snippet. Any help will be appreciated. Thank you so much

2
  • Hi, can you show desired output as well ? Commented Feb 26, 2022 at 16:06
  • 1
    This is my desired output. prnt.sc/U3-FS1wJP7hw I can already make a keys for length = 2, but for length = 1. I haven't done it yet. If the length is equal to one then it is a "no match" (Just like on the first snippet) Commented Feb 26, 2022 at 17:15

1 Answer 1

2

You can get the length of the JSON Array outside result[keys[i]] each loop and then using that length you can change your code to append "no match" for length 1 .

Demo Code :

const source = [{
    entryID: 1,
    entryName: "player1",
    weight: 1900,
  },
  {
    entryID: 2,
    entryName: "player2",
    weight: 1900,
  },
  {
    entryID: 3,
    entryName: "player3",
    weight: 1905,
  },
  {
    entryID: 4,
    entryName: "player4",
    weight: 1905,
  },
  {
    entryID: 5,
    entryName: "player5",
    weight: 1910,
  },


];

function combine(
  data = [],
  different = 0,
  maxGroupSize = 2,
  sortedStatement = (a, b) => a.weight - b.weight
) {
  const sortedData = [...data].sort(sortedStatement);
  const dataGroups = sortedData.reduce((acc, item) => {
    const findedAccItem = acc.find(
      (accItem) =>
      accItem.length < maxGroupSize &&
      accItem[0].weight + different >= item.weight &&
      !accItem.find((obj) => obj.entryName === item.entryName)
    );
    if (findedAccItem) {
      findedAccItem.push(item);
    } else {
      acc.push([item]);
    }
    return acc;
  }, []);

  const namedDataGroups = dataGroups.reduce((acc, item, index) => {

    const key = [index, ...item.map((item) => item.weight)].join("_");
    acc[key] = item;
    return acc;
  }, {});

  return namedDataGroups;
}
var result = combine(source);
var keys = Object.keys(result)
var html = ""
for (var i = 0; i < keys.length; i++) {
  var length_ = result[keys[i]].length; //get length of the json array per keys
  result[keys[i]].forEach(function(value, index) {
    var entryIDs = index == 0 ? "entryIDM[]" : "entryIDW[]";
    var players = index == 0 ? "playerM[]" : "playerW[]";
    var levels = index == 0 ? "levelM[]" : "levelW[]";
    //change to correct key name
    html += `<input type="text" name="${entryIDs}" value="${value.entryID}"> 
                 <input type="text" name="${players}" value="${value.entryName}">
                 <input type="text" name="${levels}" value="${value.weight}">`
    //if length is only one
    if (length_ == 1) {
      //just add inputs with nm..
      html += `<input type="text" name="entryIDW[]" value="nm"> <input type="text" name="playerW[]" value="nm"><input type="text" name="levelW[]" value="nm">`

    }
  })
}
document.getElementById("result").innerHTML = html //append to dom
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="result"></div>

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you it works now. Super appreciated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.