Currently, I have a function where will join 2 data with the same weight in 1 array. My target is how I can join them with a different value? I have a default value that is equal to 15 for the difference. Additional: I need to put a restriction. Only less than or greater than 15 weight differences should be in the array. If it exceeds, then it shouldn't be in the same array.
For example:
entryID:1 weight:1900 and entryID:2 1915 will be in array 1... entryID:3 weight:1915 and entryID:4 1920 will be in array 2.
//This current snippet joins 2 data in 1 array if they have the same weight. My target is to join 2 data also in 1 array but with different weights.
const source = [{
entryID: 1,
entryName: 'player1',
weight: 1900,
},
{
entryID: 2,
entryName: 'player2',
weight: 1915,
},
{
entryID: 3,
entryName: 'player3',
weight: 1915,
},
{
entryID: 4,
entryName: 'player4',
weight: 1920,
},
{
entryID: 5,
entryName: 'player5',
weight: 1950,
},
{
entryID: 6,
entryName: 'player6',
weight: 1965,
},
]
const combine = (source) => {
return source.reduce((acc, curr) => {
if (acc[curr.weight]) {
const levelArr = acc[curr.weight];
const last = levelArr[levelArr.length - 1];
if (last.length === 2) {
levelArr.push([curr])
} else {
last.push(curr)
}
} else {
acc[curr.weight] = [
[curr]
];
}
return acc;
}, {})
};
var result = combine(source)
var html = ""
var keys = Object.keys(result) //if there are more than one keys i.e : 2..
for (var i = 0; i < keys.length; i ) {
result[keys[i]].forEach(function(val) {
val.forEach(function(value, index) {
var entryIDs = index == 0 ? "entryIDM[]" : "entryIDW[]"
var handlers = index == 0 ? "handlerM[]" : "handlerW[]"
var weights = index == 0 ? "weightM[]" : "weightW[]"
html = `<input type="text" name="${entryIDs}" value="${value.entryID}">
<input type="text" name="${handlers}" value="${value.entryName}">
<input type="text" name="${weights}" value="${value.weight}">
`
})
})
}
document.getElementById("result").innerHTML = html
console.log(result);
<div id="result">
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
My expected output:
{
1900_1915: [[{
entryID: 1,
entryName: "player1",
weight: 1900
}, {
entryID: 2,
entryName: "player2",
weight: 1915
{
1915_1920: [[{
entryID: 3,
entryName: "player3",
weight: 1915
}, {
entryID: 4,
entryName: "player4",
weight: 1920
}
CodePudding user response:
Here is one way to do it. You can adjust the difference
value that is used to combine data.
const source = [
{ entryID: 1,entryName: 'player1', weight: 1900 },
{ entryID: 2, entryName: 'player2', weight: 1915 },
{ entryID: 3, entryName: 'player3', weight: 1915 },
{ entryID: 4, entryName: 'player4', weight: 1920 },
{ entryID: 5, entryName: 'player5', weight: 1950 },
{ entryID: 6, entryName: 'player6', weight: 1965 },
]
function newCombine(data, difference) {
let nonMatched = [...data]
const groups = {}
for (let i = 0; i < nonMatched.length - 1; i ) {
const first = nonMatched[i]
inner: for (let j = nonMatched.length - 1; j > i; j--) {
const second = nonMatched[j]
const delta = Math.abs(first.weight - second.weight)
if (delta <= difference) {
const groupKey = `${first.weight}_${second.weight}`
groups[groupKey] = [first, second]
nonMatched = nonMatched.filter(
obj => obj.entryID != first.entryID && obj.entryID != second.entryID
)
i = -1
break inner
}
}
}
return { ...groups, ...nonMatched }
}
const a = newCombine(source, 15)
console.log(a)
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
EDIT:
In the above snippet, weight value is being used set a key for the grouped data. This is going to cause issues if there are multiple players with the same weight value. The following input:
const source = [
{ entryID: 1, entryName: 'player1', weight: 1900 },
{ entryID: 2, entryName: 'player2', weight: 1915 },
{ entryID: 3, entryName: 'player3', weight: 1915 },
{ entryID: 4, entryName: 'player4', weight: 1915 },
{ entryID: 5, entryName: 'player5', weight: 1915 },
]
will output:
{
'0': { entryID: 1, entryName: 'player1', weight: 1900 },
'1915_1915': [
{ entryID: 3, entryName: 'player3', weight: 1915 },
{ entryID: 4, entryName: 'player4', weight: 1915 }
]
}
Which resulted in some entries being deleted. So it would be better to use a more unique value for the keys such as entryID
:
const groupKey = `${first.entryID}_${second.entryID}`
CodePudding user response:
If I understand your question correctly, you want to group them by their weight. Then you can use the same logic when you check if the list has the same weight.
You don't need to check if they have them same weight, because the dictionary will have their weight as a key.
const combine = (source) => {
return source.reduce((acc, curr) => {
const wList = acc[curr.weight] || [];
wList.push(curr);
acc[curr.weight] = wList;
return acc;
}, {})
};
If you need input validation:
const combine = (source) => {
return source.reduce((acc, curr) => {
// If not greater or less than 15, means not 15
if (curr.weight != 15) {
return acc;
}
// values here are valid
const wList = acc[curr.weight] || [];
wList.push(curr);
acc[curr.weight] = wList;
return acc;
}, {})
};