Related
I have a 2d array where I need to generate the report.
The names of employees working is maintained in the schedule, and the replacements for the day is mentioned. So a report needs to be generated and the expected result to be for the sample data is
Name#1: 24,26 Jan ----> Name#2
Name#5: 23 - 27 Jan ----> Name#4
Name#6: 23, 25-27 Jan ----> Name#3
I have tried using JS, But I am struggling to understand the way it works.
function display() {
const values = [
["Name/Date", "2023-01-22T18:30:00.000Z", "2023-01-23T18:30:00.000Z", "2023-01-24T18:30:00.000Z", "2023-01-25T18:30:00.000Z", "2023-01-26T18:30:00.000Z"],
["Name#1", "", "Name#2", "", "Name#2", ""],
["Name#2", "", "", "", "", ""],
["Name#3", "", "", "", "", ""],
["Name#4", "", "", "", "", ""],
["Name#5", "Name#4", "Name#4", "Name#4", "Name#4", "Name#4"],
["Name#6", "Name#3", "", "Name#3", "Name#3", "Name#3"]
]
for (var i = 1; i < values.length; i++) {
if (values[i][0]) {
var string = [];
for (var j = 1; j < values[i].length; j++) {
if (values[i][j]) {
string.push(values[i][j])
}
}
}
console.log(schedule)
}
}
You could add some checks for the last name.
function display() {
const
values = [["Name/Date", "2023-01-22T18:30:00.000Z", "2023-01-23T18:30:00.000Z", "2023-01-24T18:30:00.000Z", "2023-01-25T18:30:00.000Z", "2023-01-26T18:30:00.000Z"], ["Name#1", "", "Name#2", "", "Name#2", ""], ["Name#2", "", "", "", "", ""], ["Name#3", "", "", "", "", ""], ["Name#4", "", "", "", "", ""], ["Name#5", "Name#4", "Name#4", "Name#4", "Name#4", "Name#4"], ["Name#6", "Name#3", "", "Name#3", "Name#3", "Name#3"]],
result = [];
for (let i = 1; i < values.length; i++) {
let row;
for (let j = 1; j < values[i].length; j++) {
if (!values[i][j]) continue;
if (values[i][j - 1] === values[i][j]) {
row[2] = '-';
row[3] = values[0][j].slice(0, 10);
} else {
const date = values[0][j].slice(0, 10);
row = [values[i][0], date, ',', date, values[i][j]];
result.push(row);
}
}
}
return result;
}
console.log(display());
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here is a refactored version of the code to generate the report string as described:
function display() {
const values = [ ["Name/Date", "2023-01-22T18:30:00.000Z", "2023-01-23T18:30:00.000Z", "2023-01-24T18:30:00.000Z", "2023-01-25T18:30:00.000Z", "2023-01-26T18:30:00.000Z"],
["Name#1", "", "Name#2", "", "Name#2", ""],
["Name#2", "", "", "", "", ""],
["Name#3", "", "", "", "", ""],
["Name#4", "", "", "", "", ""],
["Name#5", "Name#4", "Name#4", "Name#4", "Name#4", "Name#4"],
["Name#6", "Name#3", "", "Name#3", "Name#3", "Name#3"]
]
for (var i = 1; i < values.length; i++) {
var working = [];
var replacing = "";
for (var j = 1; j < values[i].length; j++) {
if (values[i][j]) {
if (!replacing) {
replacing = values[i][j];
}
working.push(j);
} else if (replacing) {
console.log(`${values[i][0]}: ${new Date(values[0][working[0]]).toLocaleDateString()} ${working.length > 1 ? "-" : ","} ${new Date(values[0][working[working.length - 1]]).toLocaleDateString()} ----> ${replacing}`);
working = [];
replacing = "";
}
}
if (replacing) {
console.log(`${values[i][0]}: ${new Date(values[0][working[0]]).toLocaleDateString()} ${working.length > 1 ? "-" : ","} ${new Date(values[0][working[working.length - 1]]).toLocaleDateString()} ----> ${replacing}`);
}
}
}
Let's say, I have an Array of object:
var jsonData = [{
"Mass": "3",
"Force": "3.1",
"Acceleration": "3"
}, {
"Mass": "3",
"Force": "4.1",
"Acceleration": "3"
}, {
"Mass": "4",
"Force": "4.1",
"Acceleration": "4"
}, {
"Mass": "4",
"Force": "4.1",
"Acceleration": "4"
}, {
"Mass": "0",
"Force": "0",
"Acceleration": "0"
}, {
"Mass": "0",
"Force": "0",
"Acceleration": "0"
}];
What I want is to convert this JSON to a table like this for each of
2 objects serially where Mass and Acceleration cells are merged.
You can do this with reduce method and % operator to add element to an array on every 2nd element and then based on that new array you can build table.
var jsonData = [{"Mass":"3","Force":"3.1","Acceleration":"3"},{"Mass":"3","Force":"4.1","Acceleration":"3"},{"Mass":"4","Force":"4.1","Acceleration":"4"},{"Mass":"4","Force":"4.1","Acceleration":"4"},{"Mass":"0","Force":"0","Acceleration":"0"},{"Mass":"0","Force":"0","Acceleration":"0"}]
const result = jsonData.reduce((r, e, i, a) => {
// when index is 0, 2, 4 ... (every 2nd)
if (i % 2 == 0) {
// get also the next element 1, 3, 5
const next = a[i + 1];
// create a copy of current element and force as array
const obj = { ...e, Force: [e.Force] }
// if there is next element push its force to array
if (next) obj.Force.push(next.Force);
// push that new object to accumulator
r.push(obj)
}
return r;
}, []);
const table = $('table');
const thead = table.find('thead');
const tbody = table.find('tbody');
Object.keys(result[0]).forEach(key => {
thead.append($('<th>', {
text: key
}))
})
result.forEach(e => {
const row = $('<tr>');
row.append($('<td>', {
text: e.Mass
}));
const force = $('<td>');
e.Force.forEach(f => {
const forceRow = $("<tr>");
forceRow.append($('<td>', {
text: f
}));
force.append(forceRow);
});
row.append(force);
row.append($('<td>', {
text: e.Acceleration
}));
tbody.append(row)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1">
<thead></thead>
<tbody></tbody>
</table>
I have an array like:
["", "", "", "1", "", ""]
I want to alert when all the array values are blanks, i.e, when the array is like this:
["", "", "", "", "", ""]
How can I achieve this.
Use every():
const allEmpty = arr => arr.every(e => e === "");
console.log(allEmpty(["", "", "", "1", "", ""]));
console.log(allEmpty(["", "", "", "", "", ""]));
Try this,
["", "", "", "", "", ""].join("").length==0
If you want to remove spaces,
["", "", "", "", "", ""].join("").replace(/\s/gi,'').length==0
Note :
This will not work for inputs like ["", [], "", null, undefined, ""]
TL;DR (Fastest & Simple)
[].some(Boolean) // Empty : false | Not Empty : true
Explanation
Mixture of native functions, Boolean with .some() or .filter() or using .join() can return the expected result:
var a=['','','','',''], // Empty
b=['','','x','','']; // Not Empty
// Is Not Empty?
// #1
console.log( a.some(Boolean) ); // false
console.log( b.some(Boolean) ); // true
// #2
console.log( a.filter(Boolean).length ); // = 0
console.log( b.filter(Boolean).length ); // != 0
// #3
console.log( a.join('')!='' ); // false
console.log( b.join('')!='' ); // true
Also a user-defined function:
var a=['','','','',''], // Empty
b=['','','x','','']; // Not Empty
function isArrayEmpty(a) {
for (var i = 0; i < a.length; i++)
if (a[i]) return false;
return true;
}
console.log( isArrayEmpty(a) ); // true
console.log( isArrayEmpty(b) ); // false
But about performance:
.some(Boolean) ~40M ops/s (Operation per second)
isArrayEmpty() ~36M ops/s (~10% slower)
.filter(Boolean).length ~9M ops/s (~75% slower)
.join('')!='' ~4M ops/s (~90% slower)
Note (1): Using Arrow functions (a)=>a instead of Boolean, will make the performances even lower, in these cases about ~5% slower.
Note (2): The expected result is same just when we are sure that all of array items are String. About other falsy s (null or false ...) items, the option #3 (join) will not work.
You can always use a basic for loop as a solution for your problem:
function allBlanks(arr)
{
for (var i = 0; i < arr.length; i++)
{
if (arr[i] !== "") return false;
}
return true;
}
console.log(allBlanks(["", "", "", "1", "", ""]));
console.log(allBlanks(["", "", "", "", "", ""]));
console.log(allBlanks(["", [], "", null, undefined, ""]));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Here is also a more generic approach which would compact the array removing all falsey values and then check the remaining length:
let compact = a => a.reduce((r,c) => (!!c ? r.push(c) : null, r),[])
let isEmpty = array => compact(array).length == 0
console.log(isEmpty(["", false, 0, "", null, undefined])) // true
console.log(isEmpty(["", 1])) // false
console.log(isEmpty(["", []])) // false
console.log(isEmpty(["", {}])) // false
But if this is the only use case you care about then you can also use Array.some:
let isEmpty = a => !a.some(x => x !== '')
// OR let isEmpty = a => !a.some(x => x.toString().length > 0)
console.log(isEmpty(["", "", "", "", "", ""]))
console.log(isEmpty(["", "", "1", "", "", ""]))
You could also use Array.reduce:
let isEmpty = a => !a.reduce((r,c) => `${r}${c}`).length
console.log(isEmpty(["", "", "", "", "", ""]))
console.log(isEmpty(["", "", "1", "", "", ""]))
Array.filter:
let isEmpty = a => !a.filter(x => x.toString().length).length
console.log(isEmpty(["", "", "", "", "", ""]))
console.log(isEmpty(["", "", "1", "", "", ""]))
This will only be valid check against your current input however. Not against cases with arrays, object literals etc as part of your input array.
If you are using lodash this could be (via _.every and _.isEmpty):
let isArrayEmpty = a => _.every(a, _.isEmpty)
console.log(isArrayEmpty(["", "", "", "", "", ""]))
console.log(isArrayEmpty(["", "", "1", "", "", ""]))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
or also via _.compact which also removes falsey values:
let isArrayEmpty = a => !_.compact(a).length
console.log(isArrayEmpty(["", "", "", "", "", ""]))
console.log(isArrayEmpty(["", "", "1", "", "", ""]))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
const isEmpty=arr=>{
return arr.filter(it=>it.length>0).length ==0
}
arr1 = ["",""]
arr2 = ["1",""]
console.log(isEmpty(arr1))
console.log(isEmpty(arr2))
var arr1 = ["", "", "", "1", "", ""];
var arr2 = ["", "", "", "", "", ""];
function checkArrValEmpty(arr) {
let count = 0;
for(let i = 0; i < arr.length; i++) {
if(arr[i].trim().length === 0) {`enter code here`
count++;
}
}
return count === arr.length
}
console.log(checkArrValEmpty(arr2));
console.log(checkArrValEmpty(arr1));
function isEmpty (arr){
return arr.every(e => e === "")
};
let a = ["", "", "", "1", "", ""];
let b = ["", "", "", "", "", ""]
console.log(isEmpty(a));
console.log(isEmpty(b));
I implemented small function for checking empty array which will work in all browsers.
var list=["1", [], "", null, undefined, ""];
var listE=["", "", "","", "", "", ""];
var listE1=["", [], "", null, undefined, ""];
function isArrayEmpty(arr){
return arr.toString().replace(/,/g, '')=="";
}
alert(isArrayEmpty(list))
alert(isArrayEmpty(listE))
alert(isArrayEmpty(listE1))
1) Maintain the size of array as length 2) Find the no. of empty values in the array and store it in say an variable (EmptyValues)
3) Check if (EmptyValue== length) { Give Alert whatever you want}
function checkBlankvalues(arr){
var emptyValues=0,length=arr.length;
//for finding empty vales in array till now
for(var i=0;i<arr.length;i++)
{
if(arr[i]="")
{
emptyValues++;
}
}
if(length==emptyValue)
{
//alert("array is blank");
}
}
I receive a JSON result message in the following format from an old database query that I do not have the ability to change at this time:
{
"vsm1": "2429",
"vsm2": "2488",
"vsm3": "1968",
"vsm4": "",
"vsm5": "",
"vsm6": "",
"vsm7": "",
"vsm8": "",
"vsm9": "",
"vsm10": "",
"color1": "5",
"color2": "4",
"color3": "4",
"color4": "0",
"color5": "0",
"color6": "0",
"color7": "0",
"color8": "0",
"color9": "0",
"color10": "0",
"p1mtime": "1549296004",
"p2mtime": "1549296009",
"p3mtime": "1549296014",
"p4mtime": "",
"p5mtime": "",
"p6mtime": "",
"p7mtime": "",
"p8mtime": "",
"p9mtime": "",
"p10mtime": "",
"inch1": "",
"inch2": "",
"inch3": "",
"inch4": "",
"inch5": "",
"inch6": "",
"inch7": "",
"inch8": "",
"inch9": "",
"inch10": ""
}
I would like to re-format it to a more useable object, like so:
{ id: 1, vsm: 2429, color: 5, pmtime: 1549296004, inch: 0 }
{ id: 2, vsm: 2488, color: 4, pmtime: 1549296009, inch: 0 }
{ id: 3, vsm: 1968, color: 4, pmtime: 1549296014, inch: 0 }
...and so on.
The incoming data is currently limited to ten of each 'section' (vsm1, vsm2, ...vsm10, color1, color2, ...color10, etc.), so a static loop of some sort over the ten elements in each section is how i started, but seemed rather ugly and certainly not flexible.
A smart snippet that would handle n-number of elements in each section would be even better just in case the data goes beyond ten elements, or drops to just three (due to absence of data or pruned data).
I'm thinking of something along the lines of using .forEach(), but admittedly my JSON / Object manipulation skills are rather poor, so I turn to the community in the hope that someone can point me in the right direction or knows of a cool, tight routine/function that achieves what I'm looking for. Thanks in advance for any insights.
You could take an array of the wanted keys with a placeholder for the running number and build new object and push them to the result set.
var data = { vsm1: "2429", vsm2: "2488", vsm3: "1968", vsm4: "", vsm5: "", vsm6: "", vsm7: "", vsm8: "", vsm9: "", vsm10: "", color1: "5", color2: "4", color3: "4", color4: "0", color5: "0", color6: "0", color7: "0", color8: "0", color9: "0", color10: "0", p1mtime: "1549296004", p2mtime: "1549296009", p3mtime: "1549296014", p4mtime: "", p5mtime: "", p6mtime: "", p7mtime: "", p8mtime: "", p9mtime: "", p10mtime: "", inch1: "", inch2: "", inch3: "", inch4: "", inch5: "", inch6: "", inch7: "", inch8: "", inch9: "", inch10: "" },
keys = ['vsm*', 'color*', 'p*mtime', 'inch*'],
result = [],
id = 1;
while (keys[0].replace('*', id) in data) {
result.push(Object.assign(
{ id },
...keys.map(k => ({ [k.replace('*', '')]: +data[k.replace('*', id)] || 0 }))
));
id++;
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
With template literals
var data = { vsm1: "2429", vsm2: "2488", vsm3: "1968", vsm4: "", vsm5: "", vsm6: "", vsm7: "", vsm8: "", vsm9: "", vsm10: "", color1: "5", color2: "4", color3: "4", color4: "0", color5: "0", color6: "0", color7: "0", color8: "0", color9: "0", color10: "0", p1mtime: "1549296004", p2mtime: "1549296009", p3mtime: "1549296014", p4mtime: "", p5mtime: "", p6mtime: "", p7mtime: "", p8mtime: "", p9mtime: "", p10mtime: "", inch1: "", inch2: "", inch3: "", inch4: "", inch5: "", inch6: "", inch7: "", inch8: "", inch9: "", inch10: "" },
templates = [id => `vsm${id}`, id => `color${id}`, id => `p${id}mtime`, id => `inch${id}`],
result = [],
id = 1;
while (templates[0](id) in data) {
result.push(Object.assign(
{ id },
...templates.map(t => ({ [t('')]: +data[t(id)] || 0 }))
));
id++;
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try this, with oldObject the object you want to clean:
var cleanedObject = {};
for (let [key, value] of Object.entries(oldObject)) {
let index = key.match('[0-9]+');
cleanedObject[index] = cleanedObject[index] || {};
cleanedObject[index][key.replace(index, '')] = value;
}
The result will be an object where cleanedObject['1'] = { vsm: 2429, color: 5, pmtime: 1549296004, inch: '' }, and so on.
This solution has a different flexibility than the one from Nina Sholz. Nina's allows you to match any style of number-containing key. But it also requires you to add a template in order to do so. Mine will handle any keys which contain only a single run of digits but nothing more complex. But it doesn't require you to do anything to handle such templates.
const reformat = data => Object.values(Object.keys(data)
.reduce(
(a, k, i, _, d = k.match(/\d+/)[0]) => ({
...a,
[d]: {...(a[d] || {id: Number(d)}), [k.replace(/\d+/, '')]: data[k]}
}), {})).sort((a, b) => a.id - b.id)
const data = {"vsm1":"2429","vsm2":"2488","vsm3":"1968","vsm4":"","vsm5":"","vsm6":"","vsm7":"","vsm8":"","vsm9":"","vsm10":"","color1":"5","color2":"4","color3":"4","color4":"0","color5":"0","color6":"0","color7":"0","color8":"0","color9":"0","color10":"0","p1mtime":"1549296004","p2mtime":"1549296009","p3mtime":"1549296014","p4mtime":"","p5mtime":"","p6mtime":"","p7mtime":"","p8mtime":"","p9mtime":"","p10mtime":"","inch1":"","inch2":"","inch3":"","inch4":"","inch5":"","inch6":"","inch7":"","inch8":"","inch9":"","inch10":""}
console.log(reformat(data))
I have no idea if you need either sort of flexibility, but these are interesting alternatives to one another.
I now see that my answer is basically the same as Ninas, haven't seen templating before so that was cool, but seeing as this i the first time i've tried to answer something here I'll just share it anyway.
As Ninas this can handle any length of data.
const data = {"vsm1": "2429",
"vsm2": "2488",
"vsm3": "1968",
"vsm4": "",
"color1": "5",
"color2": "4",
"color3": "4",
"color4": "0",
"p1mtime": "1549296004",
"p2mtime": "1549296009",
"p3mtime": "1549296014",
"p4mtime": "",
"inch1": "",
"inch2": "",
"inch3": "",
"inch4": "",
};
const vsmRegex = new RegExp("(vsm\\d)");
const keys = Object.keys(data);
const result = [];
let id= 1;
for(let i = 0; i < keys.length; i++) {
if(keys[i].match(vsmRegex)) {
let object = {
id: id,
vsm: Number(data[`vsm${id}`]) || 0,
color: Number(data[`color${id}`]) || 0,
pmtime: Number(data[`p${id}mtime`]) || 0,
inch: Number(data[`inch${id}`]) || 0
};
result.push(object);
id++;
} else {
break;
}
}
console.log(result);
I'm receiving this JSON below
{
"category": "test",
"sealing_temp_1": "",
"sealing_temp_2": "",
"sealing_temp_3": "",
"level_sensor_1": "",
"level_sensor_2": "",
"level_sensor_3": "",
"check_pack_1": "",
"check_pack_2": "",
"check_pack_3": "",
"comment": ""
}
and I would like to turn it to this structure and save
{
"category": "test",
"sealing_temp": "['a', 'b', 'c']",
"level_sensor": "['x', 'y', 'z']",
"check_pack": "[1, 2, 3]",
"comment": ""
}
Can someone guide me, I tried to use a for..in but got lost in the process
You could split the key and if it has digits at the end in it, then use it for an array to fill.
This proposal change the object and deletes unwanted properties which values are now in an array collected.
var object = { category: "test", sealing_temp_1: "s1", sealing_temp_2: "s2", sealing_temp_3: "s3", level_sensor_1: "l1", level_sensor_2: "l2", level_sensor_3: "l3", check_pack_1: "c1", check_pack_2: "c2", check_pack_3: "c3", comment: "cc" };
Object.keys(object).forEach(function (k) {
var parts = k.split(/_(?=\d+$)/);
if (parts.length === 2) {
object[parts[0]] = object[parts[0]] || [];
object[parts[0]][parts[1] - 1] = object[k]; // subtract one for zero based array
delete object[k];
}
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }