I am trying to make a javaScript game of housie/bingo game. I used the library npm tambola-generator which returns auto generated tickets.
The server side process generates an array similar to this one ...
[{
"_entries": [[0,17,0,0,41,53,0,78,86], [4,0,0,35,0,58,67,80,0]/*, [ ... ] */],
}, {
"_entries": [[0,16,23,0,41,51,0,0,88], [2,20,0,31,43,56,0,0,0]/*, [ ... ] */],
}, {
"_entries": [[0,0,23,33,0,51,0,73,87], [1,0,0,35,42,58,68,0,0]/*, [ ... ] */],
}, {
// ... more items like that ...
}]
I want each ticket to feature a serial number which should be equal to a ticket items's array index but starting with the base of 1 instead of 0.
How does one include such a ticket number so that I can manage tickets for players?
I am just a beginner I couldn't solve it out. The target structure of the above example code should look like the following one ...
[{
"ticketNum": 1,
"_entries": [[0,17,0,0,41,53,0,78,86], [4,0,0,35,0,58,67,80,0]/*, [ ... ] */],
}, {
"ticketNum": 2,
"_entries": [[0,16,23,0,41,51,0,0,88], [2,20,0,31,43,56,0,0,0]/*, [ ... ] */],
}, {
"ticketNum": 3,
"_entries": [[0,0,23,33,0,51,0,73,87], [1,0,0,35,42,58,68,0,0]/*, [ ... ] */],
}, {
// ... more items like that ...
}]
Just use Array.prototype.map for achieving this task.
const entries = [{
"_entries": [
[0, 17, 0, 0, 41, 53, 0, 78, 86],
[4, 0, 0, 35, 0, 58, 67, 80, 0]
],
}, {
"_entries": [
[0, 16, 23, 0, 41, 51, 0, 0, 88],
[2, 20, 0, 31, 43, 56, 0, 0, 0]
],
}, {
"_entries": [
[0, 0, 23, 33, 0, 51, 0, 73, 87],
[1, 0, 0, 35, 42, 58, 68, 0, 0]
],
}];
const tcktEntries = entries.map((entry, index) => {
return {
ticketNum: index + 1,
...entry
};
});
console.log({
tcktEntries
});
.as-console-wrapper {
min-height: 100%!important;
top: 0;
}
Related
i have a json and need to extract data to array.
const data = [{
"week": 1,
"lost": 10,
"recovery_timespan": [{
"week": 2,
"count": 1
}, {
"week": 3,
"count": 0
}],
"netLost": 10,
"netReturned": 20
}, {
"week": 2,
"lost": 7,
"recovery_timespan": [{
"week": 3,
"count": 1
}],
"netLost": 30,
"netReturned": 200
}, {
"week": 3,
"lost": 8,
"recovery_timespan":"",
"netLost": 50,
"netReturned": 40
}];
Expected output: lost,count in recovery_timespan,netLost , netReturned.
[ [ 10, 1, 0, 10, 20 ], [ 7, 1, 30, 200 ], [ 8, 50, 40 ] ]
As you can see expected output, last recovery_timespan does not contain any data and it just shows as "".so i need to ignore it.
My approach:
const result = data.map(({lost, recovery_timespan,netLost,netReturned}) => [
lost,
...recovery_timespan.map(({count}) => count),
netLost,netReturned
]);
My code breaks when "recovery_timespan" is "". How can i add a filter along with map to filter that part and make my code work?
It's just a matter of checking if it's string or not, but you can short circuit
const result = data.map(({lost, recovery_timespan,netLost,netReturned}) => [
lost,
...(recovery_timespan || []).map(({count}) => count),
netLost,netReturned
]);
How to filter data from array of array?.
pls find the explanation in below given example.
We must use startnumber and endnumber in data query.
const data = [
{
"name": "x",
"points": [
[100, 50, 1], //[number, value, bit]
[150, 51, 0],
[170, 52, 1],
[200, 53, 0]
]
},
{
"name": "y",
"points": [
[60, 50, 1],
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
[200, 53, 1]
]
},
{
"name": "z",
"points": [
[300, 50, 1],
[350, 51, 0],
[370, 52, 1],
[400, 53, 1]
]
}
]
// want to find the records with name equal to x & y and number between 100 to 170
const names = ["x", "y"];
const startnumber = 100;
const endnumber = 170;
const finalResult= [];
for(const n of names){
console.log('name', n);
console.log('startnumber', startnumber)
console.log('endnuumber', endnumber)
const result = data.find(x=>x.name === n)
// how to use startnumber and endnumber here in above line/query ? OR some other elegant solution is required
if(result){
finalResult.push('result', result);
}
}
if(finalResult.length){
console.log(finalResult);
}
Expected result should be
[
{
"name": "x",
"points": [
[100, 50, 1],
[150, 51, 0],
[170, 52, 1],
]
},
{
"name": "y",
"points": [
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
]
}
]
const results = data.filter(elem => !!names.find(name => name == elem.name))
Explanation:
data.filter applies the callback to each element of the array data
names.find applies the callback to each element of the array names in order to find a match.
!! is used because find returns an element, so !! causes a double negation that turns it into a boolean, the expected return from the find callback (its actually not strictly necessary, as find returning undefined would be coerced to false), but it clarifies the intention.
The result is only the elements of data that have names properties that match the values in names.
const data = [
{
"name": "x",
"points": [
[100, 50, 1], //[number, value, bit]
[150, 51, 0],
[170, 52, 1],
[200, 53, 0]
]
},
{
"name": "y",
"points": [
[60, 50, 1],
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
[200, 53, 1]
]
},
{
"name": "y",
"points": [
[60, 50, 1],
[200, 53, 1]
]
},
{
"name": "z",
"points": [
[300, 50, 1],
[350, 51, 0],
[370, 52, 1],
[400, 53, 1]
]
}
]
// want to find the records with name equal to x & y and number between 100 to 170
const names = ["x", "y"];
const startNumber = 100;
const endNumber = 170;
const results = data
.filter(elem => !!names.find(name => name == elem.name))
.map(elem => {
return {
name: elem.name,
points: elem.points.filter(point => point[0] >= startNumber && point[0] <= endNumber)
}
})
.filter(elem => elem.points.length > 0)
console.log(results)
The most elegant solution:
const res = data.reduce((acc, curr) => {
const { name, points } = curr
const filteredPoints = points.filter(p => p[0] >= startNumber && p[0] <= endNumber)
return names.includes(name) && filteredPoints.length > 0 ? acc.concat({ name, points: filteredPoints }) : acc
}, [])
The task and the two given data structures imply a two folded filter process for each data item.
Identifying the data item by its name (from the additionally provided names array).
Filtering each data item's points array by whether a points item's first array item (the number value) is within a certain number range (which is defined by the additionally provided startnumber and endnumber values).
Thus a viable approach was to reduce the provided data array by a reducer function which for each data item takes care of the above two tasks.
The reducer function's initial value will be kind of a config and/or collector object which features ...
a name lookup (applied as a Map instance) for the to be explicitly processed data items.
the startnumber and endnumber range values as lowerNumber respectively upperNumber.
and a result array where only those data items get pushed into which fulfill all requirements.
function collectItemsByNameWhichHavePointsInNumberRange(collector, item) {
const { nameLookup, lowerNumber, upperNumber, result } = collector;
let { name, points } = item;
// ... collect items by name ...
if (nameLookup.has(name)) {
points = points
.filter(([number]) =>
(number >= lowerNumber) && (number <= upperNumber)
);
// ... which (actually do) have points (with)in (a) number range.
// (according to the above `points` filter result)
if (points.length >= 1) {
result
.push({
...item,
points,
});
}
}
return collector;
}
const data = [{
name: "x",
points: [
//[number, value, bit]
[100, 50, 1],
[150, 51, 0],
[170, 52, 1],
[200, 53, 0],
],
}, {
name: "y",
points: [
[60, 50, 1],
[100, 5, 1],
[150, 6, 0],
[170, 7, 1],
[200, 53, 1],
],
}, {
name: "z",
points: [
[300, 50, 1],
[350, 51, 0],
[370, 52, 1],
[400, 53, 1],
],
}];
const names = ["x", "y"];
const startnumber = 100;
const endnumber = 170;
const { result } = data
.reduce(collectItemsByNameWhichHavePointsInNumberRange, {
nameLookup: new Map(names.map(value => [value, value])),
lowerNumber: startnumber,
upperNumber: endnumber,
result: [],
});
console.log({ result });
.as-console-wrapper { min-height: 100%!important; top: 0; }
I need to compare id objects array from a firstArray and array numbers (secondArray) and return a new array with objects from the first array which id number exists in the second array.
So at the end, I want a new array with objects with id 39 and 41.
Actually I find something like this:
const result = arr2.filter(o => arr1.find(x => x.id === o));
const arr1 =
"blocks": [
{
"id": 1,
"functions": [ 0, 1 ]
},
{
"id": 39,
"functions": [ 0, 1, 3, 4 ]
},
{
"id": 41,
"functions": [ 0, 1 ]
}
]
const arr2 = [39, 41]
You can use includes() function during filtering. Includes() works like in array function.
const arr1 =
[ {
"id": 1,
"functions": [ 0, 1 ] },
{
"id": 39,
"functions": [ 0, 1, 3, 4 ]
},
{
"id": 41,
"functions": [ 0, 1 ]
}
]
const arr2 = [39, 41]
const result = arr1.filter(o => arr2.includes(o.id));
console.log(result)
You can create a Map to see whether there is an item of Map exists in filtering array. Getting an item from Map method is O(1):
const blocks = [
{
"id": 1,
"functions": [
0,
1
]
},
{
"id": 39,
"functions": [
0,
1,
3,
4
]
},
{
"id": 41,
"functions": [
0,
1
]
}
];
const arr2 = [39, 41];
const arr2Maps = new Map(arr2.map(a=>[a, a]));
const result = blocks.filter(o => arr2Maps.get(o.id));
console.log(result)
In addition, you can use filter and some methods. However, some method has O(n):
const blocks = [
{
"id": 1,
"functions": [
0,
1
]
},
{
"id": 39,
"functions": [
0,
1,
3,
4
]
},
{
"id": 41,
"functions": [
0,
1
]
}
];
const arr2 = [39, 41]
const result = blocks.filter(o => arr2.some(a=> a ==o.id ));
console.log(result)
Trying to write a regex for my text editor (BBEdit) to encode strings that are not already quoted within an almost correctly syntaxed JSON style object so that I can use within a JavaScript context that would otherwise see these text strings as undefined variables.
Thus :
[ 0, 0, Header, 1, 17, 480 ],
[ 1, 0, Start_track ],
[ 1, 0, Title_t, "Dance of the knights (Romeo & Juliet)" ],
[ 1, 0, Tempo, 600000 ],
[ 1, 0, Time_signature, 4, 2, 24, 8 ],
[ 1, 0, Key_signature, 1, "major" ]
would become:
[ 0, 0, "Header", 1, 17, 480 ],
[ 1, 0, "Start_track" ],
[ 1, 0, "Title_t", "Dance of the knights (Romeo & Juliet)" ],
[ 1, 0, "Tempo", 600000 ],
[ 1, 0, "Time_signature", 4, 2, 24, 8 ],
[ 1, 0, "Key_signature", 1, "major" ]
You could use the below regex.
([\[,]\s*)([A-Za-z_]\S*)(?=,|\s*\])
And then replace the match with $1"$2"
DEMO
Example:
> var s = '[ 1, 0, Title_t, "Dance of the knights (Romeo & Juliet)" ],';
> s.replace(/([\[,]\s*)([A-Za-z_]\S*)(?=,|\s*\])/g, '$1"$2"')
'[ 1, 0, "Title_t", "Dance of the knights (Romeo & Juliet)" ],'
How to remove duplicates on an array like below:
arr = [
[828, 187, 1, 14, 1, 25, 1417608935730],
[828, 187, 1, 14, 1, 25, 1417608935740],
[828, 187, 1, 14, 1, 25, 1417608935750],
[828, 187, 1, 14, 1, 25, 1417608935760],
[600, 578, 1, 14, 1, 25, 1417608935760],
[828, 187, 1, 14, 1, 25, 1417608935780],
[828, 187, 1, 14, 1, 25, 1417608935790]
]
Since 4th and 5th array have 1417608935760 similar value I want to delete next duplicate and keep only one.
I tried this but not working:
$.each(arr, function(i, insidearr){
if($.inArray(insidearr[6], uniqueNames) === -1)
uniqueNames.push(insidearr);
});
Pls help. Thanks in advance
You're pushing the entire row into uniqueNames. The array will never be equal to the number at the end of each row, so the $.inArray() test will always fail. You need separate arrays for just the element you're comparing and the resulting array.
var newArray = [];
var uniqueNames = {};
$.each(arr, function(i, insidearr) {
if (!(insidearr[6] in uniqueNames)) {
newArray.push(insidearr);
uniqueNames[insidearr[6]] = true;
}
});
I used an object rather than an array for uniqueNames, because searching for an object key is faster than scanning an array.
Just try with:
var uniqueArr = $.grep(arr, function(insidearr){
if ($.inArray(insidearr[6], uniqueNames) === -1) {
uniqueNames.push(insidearr[6]);
return true;
}
});
try this one:
var arr = [
[828, 187, 1, 14, 1, 25, 1417608935730],
[828, 187, 1, 14, 1, 25, 1417608935740],
[828, 187, 1, 14, 1, 25, 1417608935750],
[828, 187, 1, 14, 1, 25, 1417608935760],
[600, 578, 1, 14, 1, 25, 1417608935760],
[828, 187, 1, 14, 1, 25, 1417608935780],
[828, 187, 1, 14, 1, 25, 1417608935790]
];
var len = arr.length;
while(--len) {
if(arr[len][6] == arr[len-1][6]) {
arr.splice(len-1, 1)
}
}
console.log(arr); // here is what you want
If you don't want to manipulate arr, you just need to clone the array by var newArr = arr.slice()