Javascript convert array with null value to string - javascript

I have the array
localCostp:
0:null
1:null
2:0.5
3:null
4:null
5:null
6:0.5
7:null
8:null
and i would like to convert it in a string like the below
"[],[],[0.5],[],[],[],[0.5],[],[]"
i have tried the below
console.log("[" + Object.values(localCostp).join("],[") + "]");
but i lose the null value
"[0.5],[0.5]"
i fill the array with the below code
Array.prototype.shuffle = function() {
var r=[],c = this.slice(0);
for (let i = c.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[c[i], c[j]] = [c[j], c[i]];
}
return c;
};
Array.prototype.populateUnique = function(n) {
return Object.keys( Object( 0+Array(n) ) );
};
var getRandomInts = function(num, min, max) {
var a = [].populateUnique(max+1).slice(min);
a = a.shuffle();
return a.slice(0,num);
};
BordsIdtoFill = getRandomInts(NumOfBoardToFill,1,6);
switch(retrivePanelsPanelsbetType(configGenerateData.panelsBetType)) {
case 1: case 2:{
gameMultiplayer = 1;
} break;
case 3: case 4 : case 5: {
gameMultiplayer = 2;
} break;
case 6: {
gameMultiplayer = 2;
} break;
}
var localCostp = new Array(9);
BordsIdtoFill.forEach(function(Bord) {
localCostp[Bord]= (1*gameMultiplayer * 0.5)
});
console.log("[" + Object.values(localCostp).join("],[") + "]");
not all the array position are filled

The naive way of doing would be to
const arr = [null, null, 0.5, null, 0.5]
const processedArr = arr.map(element => {
if (element) {
return [element];
} else {
return [];
}
});
const result = JSON.stringify(processedArr);
console.log(result)
A shorter, but less readable way of doing it will be to use the following:
const arr = [null, null, 0.5, null, 0.5];
const result = `[[${arr.join('],[')}]]`;
console.log(result);

That's interesting output. :-)
In a comment you've said:
i fill the array with the below code
var localCostp = new Array(9);
BordsIdtoFill.forEach(function(Bord) {
localCostp[Bord] = (1*gameMultiplayer * 0.5);
});
not all the array position are filled
That's very different from the array you showed. The array you showed had nulls in it. That array has gaps in it. When you read the value of a gap, you get back undefined (not null).
To do it, you'll either want to use a simple for loop, a for-of loop or something other way of using the iterable from values (which includes gaps), or fill the gaps first.
For instance, this uses the iterable from values:
const string = [...localCostp.values()].map(entry => JSON.stringify(entry === undefined ? [] : [entry])).join();
Live Example:
const localCostp = new Array(9);
localCostp[2] = 0.5;
localCostp[6] = 0.5;
const string = [...localCostp.values()].map(entry => JSON.stringify(entry === undefined ? [] : [entry])).join();
console.log(string);
In another comment you've said:
if i run your code on my enviroment i take There was an error in evaluating the Pre-request Script: TypeError: localCostp.values(...)[Symbol.iterator] is not a function
That's surprising, values was added in ES2015, the same time Symbol.iterator and array spread were, but your error message makes it seem like you have the latter but not the former. I suspect you're transpiling and missing a polyfill.
Here's an ES5 version (can't use map because it won't visit the gaps):
var result = [];
for (var i = 0; i < localCostp.length; ++i) {
var entry = localCostp[i];
result[i] = JSON.stringify(entry === undefined ? [] : [entry]);
}
result = result.join();
Live Example:
var localCostp = new Array(9);
localCostp[2] = 0.5;
localCostp[6] = 0.5;
var result = [];
for (var i = 0; i < localCostp.length; ++i) {
var entry = localCostp[i];
result[i] = JSON.stringify(entry === undefined ? [] : [entry]);
}
result = result.join();
console.log(result);

You can just use Array#map to produce either [] for null value or enclose the number in square brackets, then Array#join to get the desired output:
let arr = [
null,
null,
0.5,
null,
null,
null,
0.5,
null,
null
]
let str = arr
.map(item => item === null ? "[]" : `[${item}]`)
.join();
console.log(str);

You could map the values in an array or not and stringify the data and get the string between the outer brackets.
var data = [null, null, 0.5, null, null, null, 0.5, null, null],
result = JSON.stringify(data.map(v => v === null ? [] : [v])).slice(1, -1);
console.log(result);
An example with template strings.
var data = [null, null, 0.5, null, null, null, 0.5, null, null],
result = data.map(v => `[${v === null ? '' : v}]`).join();
console.log(result);
With an array with sparse items.
var array = [, , 0.5, , , , 0.5, , ],
result = Array.from(array, (v = '') => `[${v}]`).join();
console.log(result);

Related

Javascript, getting past values for an array of objects

I have a JavaScript array of objects which looks like
var myarr = [
{'xx':'2023-01-01,,1'},
{'ss':'2023-01-01,2,1.2'},
{'dd':'2023-01-01,4,'},
{'rr':'2023-01-01,,'},
{'ff':'2023-01-01,,'},
{'gg':'2023-01-01,,'}
];
The array is actually much bigger than that, but I have cut it down for testing purposes, some of my arrays are thousands of lines long
Each object contains a date and two comma-separated values, although I have some rows which contain 3 or 4 comma separate values
What I need to do, is if any blank comma-separated value is found on any row then get the previous comma separated value from that position to a maximum of 2 times going back, although I may need to change that to a bigger number in the future
So with my example, I would get the following output
var myarr = [
{'xx':'2023-01-01,,1.6'},
{'ss':'2023-01-01,2,1.2'},
{'dd':'2023-01-01,4,1.2'},
{'rr':'2023-01-01,4,1.2'},
{'ff':'2023-01-01,4,'},
{'gg':'2023-01-01,,'}
];
I have tried to solve this with
var myarr = [
{'xx':'2023-01-01,,1'},
{'ss':'2023-01-01,2,1.2'},
{'dd':'2023-01-01,4,'},
{'rr':'2023-01-01,,'},
{'ff':'2023-01-01,,'},
{'gg':'2023-01-01,,'}
];
var maxAttempts = 3;
for (var i = 0; i < myarr.length; i++) {
var obj = myarr[i];
var values = Object.values(obj)[0].split(",");
var date = values[0];
var value1 = values[1];
var value2 = values[2];
for (var j = 1; j <= maxAttempts; j++) {
if (!value1) {
value1 = (myarr[i-j] && Object.values(myarr[i-j])[0].split(",")[1]) || " ";
}
if (!value2) {
value2 = (myarr[i-j] && Object.values(myarr[i-j])[0].split(",")[2]) || " ";
}
if (value1 && value2) {
break;
}
}
console.log(date, value1, value2);
for (var k = 3; k < values.length; k++) {
var value = values[k];
console.log(value);
}
}
but it doesn't seem to provide the expected output.
Can someone help me with what might be wrong?
Maybe you can use something like this.
const myarr = [
{ "xx": "2023-01-01,,1" },
{ "ss": "2023-01-01,2,1.2" },
{ "dd": "2023-01-01,4," },
{ "rr": "2023-01-01,," },
{ "ff": "2023-01-01,," },
{ "gg": "2023-01-01,," }
]
function fillInBlanks(arr, maxLookBack) {
return arr.map((obj, index) => {
const key = Object.keys(obj)[0]
const value = Object.values(obj)[0]
.split(",")
.map((x, n) => {
if (x === "" && index > 0) {
for (let i = index - 1; i >= Math.max(0, index - maxLookBack); --i) {
const prev = Object.values(arr[i])[0].split(",")
if (prev[n] !== "") return prev[n]
}
} else return x
})
return Object.fromEntries([
[key, value.join(",")]
])
})
}
fillInBlanks(myarr, 2).forEach(x => console.log(x))
Here's my attempt. This will also work with any number of values per row.
const maxAttempts = 2;
myarr.reduce((modifiedAccumulation, currentObject, index) => {
const [key, csv] = Object.entries(currentObject)[0];
const splitCsv = csv.split(",");
const modifiedCsv = splitCsv
.reduce((fixedArray, currentElement, csvPos) => {
let numberToUse =
currentElement === ""
? myarr
.slice(Math.max(index - maxAttempts, 0), index)
.reduceRight((proposedNum, currentPastObj) => {
if (proposedNum !== "") return proposedNum;
let candidate =
Object.entries(currentPastObj)[0][1].split(",")[csvPos];
return candidate !== "" ? candidate : "";
}, "")
: currentElement;
return [...fixedArray, numberToUse];
}, [])
.join(",");
return [...modifiedAccumulation, { [key]: modifiedCsv }];
}, []);
This approach creates a 'window' array containing the last few entries, which is used to look up prior column values.
const myarr = [{"xx":"2023-01-01,,1"},{"ss":"2023-01-01,2,1.2"},{"dd":"2023-01-01,4,"},{"rr":"2023-01-01,,"},{"ff":"2023-01-01,,"},{"gg":"2023-01-01,,"}]
const windowSize = 2
const w = [], r =
myarr.map(e=>Object.entries(e).flatMap(([k,v])=>[k,...v.split(',')]))
.map(a=>(
w.unshift(a) > windowSize+1 && w.pop(),
a.map((_,i)=>w.find(x=>x[i])?.[i])
)).map(([k,...v])=>[k,v.join()]
).map(i=>Object.fromEntries([i]))
console.log(r)

Prioritizing array values

There are 3 empty arrays (a, b, c) and another array (d) with some dynamic values. I need to pass the array values to 'a','b' and 'c' arrays as in the below pattern;
Rather than having seperate IF statements is there a way to write it simpler?
const arrayA = [];
const arrayB = [];
const arrayC = [];
const arrays = [arrayA, arrayB, arrayC];
const arrayD = ['some', 'values', 'here'];
if(arrayD.length <= 3) {
for(i=0; i<3; i++){
arrayA.push(arrays[i][i]);
}
}
EDIT! in my first version I misunderstood the question
This is one way to do it, if I understood your question correctly
const arrayA = [];
const arrayB = [];
const arrayC = [];
const arrays = [arrayA, arrayB, arrayC];
const arrayD = [1, 2, 3, 4, 5, 6, 7];
function myArray(arr) {
let temp = [
[],
[],
[]
]
if (arrayD.length <= 3) {
for (let i = 0; i < arrayD.length; i = i + 3) {
temp[0].push(arrayD[i]);
arrayD[i + 1] === undefined ? null : temp.push(arrayD[i + 1])
arrayD[i + 2] === undefined ? null : temp.push(arrayD[i + 2])
arrayA.push(temp[0])
}
} else {
let index = 0
for (let i = 0; i < arrayD.length; i = i + 3) {
arrayD[i] === undefined ? null :
temp[index].push(arrayD[i])
arrayD[i + 1] === undefined ? null : temp[index].push(arrayD[i + 1]);
arrayD[i + 2] === undefined ? null : temp[index].push(arrayD[i + 2])
index++
}
arrayA.push(...temp[0])
arrayB.push(...temp[1])
arrayC.push(...temp[2])
}
arrays.push[arrayA, arrayB, arrayC]
}
myArray(arrayD)
console.log(arrays)
The problem is simplified if we can calculate the lengths of the output arrays. These are shown in the snippet as al and bl. The third length will be the remainder after slicing away the first two. With that...
const input = [1,2,3,4,5,6,7,8];
let length = input.length;
let al = Math.ceil(length / 3);
let bl = Math.ceil((length - al )/ 2);
let a = input.slice(0, al);
let b = input.slice(al, al+bl);
let c = input.slice(al+bl);
console.log([a, b, c])

javascript - filter array of strings based on seperated ending

I have an array of strings like this:
const strings = [
"author:app:1.0.0",
"author:app:1.0.1",
"author:app2:1.0.0",
"author:app2:1.0.2",
"author:app3:1.0.1"
];
And I want to filter them so that only the ones that have the latest versions for the given "author:name" are left, thus removing ones that are not the latest (i.e. the "1.0.1" ones).
My expected result is this:
const filteredStrings = [
"author:app:1.0.1",
"author:app2:1.0.2",
"author:app3:1.0.1"
];
Any way to do this simply?
You can do it with two loops first one find new ones second one check which is bigger
const strings = [
"author:app:1.0.0",
"author:app:1.0.1",
"author:app2:1.0.0",
"author:app2:1.0.2",
"author:app3:1.0.1"
];
filteredones = [];
strings.forEach(element => {
var arr = element.split(":");
var isnew = true;
var found = filteredones.find(function(element2) {
var x = element2.split(":");
return x[1] == arr[1] && x[0] == arr[0]
});
if (found == undefined) {
filteredones.push(element);
}
});
for (var i = 0; i < filteredones.length; i++) {
element = filteredones[i];
var arr = element.split(":");
var isnew = true;
var found = strings.find(function(element2) {
var x = element2.split(":");
return x[1] == arr[1] && x[0] == arr[0] && x[2] > arr[2]
});
if (found != undefined) {
filteredones[i] = found;
}
};
console.log(filteredones);
you can check the value in the last index of the string in each of the elements of the array and if they qualify as a latest one put it to a new array.
You can use an object to store the key/version pairs, and convert to appropriate output on the end. The version comparison can be any of those found here: How to compare software version number using js? (only number)
result = {};
for (var s of input) {
// parts = ["author", "appname", "version"]
var parts = s.split(":");
var i = parts[0] + ":" + parts[1];
if (!result[i] || compareVersion(parts[2], result[i]))
// If not present or version is greater
result[i] = parts[2]; // Add to result
}
result = Object.keys(result).map(k => k + ":" + result[k])
Working demo: https://codepen.io/bortao/pen/LYVmagK
Build an object with keys as app name.
getValue method is calculate the version value so that to compare.
Update object value, when you see the version is recent (value is big).
const strings = [
"author:app:1.0.0",
"author:app:1.0.1",
"author:app2:1.0.0",
"author:app2:1.0.2",
"author:app3:1.0.1"
];
const filter = data => {
const res = {};
const getValue = item =>
item
.split(":")[2]
.split(".")
.reduceRight((acc, curr, i) => acc + curr * Math.pow(10, i), 0);
data.forEach(item => {
const app = item
.split(":")
.slice(0, 2)
.join(":");
if (!res[app] || (app in res && getValue(item) > getValue(res[app]))) {
res[app] = item;
}
});
return Object.values(res);
};
console.log(filter(strings));

Creating various arrays from a string using LOOPS

I have a string of values
"000111111122222223333333444455556666"
How could I use a loop to produce one array for index values from 0 to 3 (create an array of [000] and then another array of index values from 3 to 10, 10 to 17, 17 to 24, producing eg. [1111111, 2222222, 333333] and then another loop to produce an array of index values from 24 to 28, 28 to 32, 32 to 36, producing eg. [4444, 5555, 6666])?
So in total 3 different arrays have been created using three different for loops.
array1 = [000]
array2 = [1111111, 2222222, 333333]
array3 = [4444, 5555, 6666]
You may wish to try something line this (only a schematic solution!):
var l_Input = "000111111122222223333333444455556666" ;
var l_Array_1 = [] ;
var l_Array_2 = [] ;
var l_Array_3 = [] ;
var l_One_Char ;
for (var i = 0 ; i < l_Input.length ; i++) {
l_One_Char = l_Input.substring(i,i) ;
if (i < 3) {
l_Array_1.push(l_One_Char) ;
continue ;
}
if (i >= 3 && i < 10) {
l_Array_2.push(l_One_Char) ;
continue ;
}
:
:
}
I think this would work.
const str = '000111111122222223333333444455556666';
function makeArr(str, item) {
let firstIndex = str.indexOf(item);
let lastIndex = str.lastIndexOf(item) + 1;
return [ str.substring(firstIndex, lastIndex) ];
}
const first = makeArr(str, 0);
const second = [].concat(makeArr(str, 1))
.concat(makeArr(str, 2))
.concat(makeArr(str, 3));
const third = [].concat(makeArr(str, 4))
.concat(makeArr(str, 3))
.concat(makeArr(str, 3));
You could map the sub strings.
var str = '000111111122222223333333444455556666',
parts = [[3], [7, 7, 7], [4, 4, 4]],
result = parts.map((i => a => a.map(l => str.slice(i, i += l)))(0));
console.log(result);
function split(string, start, end) {
var result = [],
substring = string[start],
split;
for (var i = start + 1; i < end; i++) {
var char = string[i];
if (char === substring[0])
substring += char;
else {
result.push(substring);
substring = char;
}
}
result.push(substring);
return result;
}
split("00011122",0,8)
["000", "111", "22"]
To do this dynamically, you can use .split() and .map() methods to make an array from your string then group this array items by value.
This is how should be our code:
const str = "000111111122222223333333444455556666";
var groupArrayByValues = function(arr) {
return arr.reduce(function(a, x) {
(a[x] = a[x] || []).push(x);
return a;
}, []);
};
var arr = str.split("").map(v => +v);
var result = groupArrayByValues(arr);
This will give you an array of separate arrays with similar values each.
Demo:
const str = "000111111122222223333333444455556666";
var groupArrayByValues = function(arr) {
return arr.reduce(function(a, x) {
(a[x] = a[x] || []).push(x);
return a;
}, []);
};
var arr = str.split("").map(v => +v);
var result = groupArrayByValues(arr);
console.log(result);

Make combinations of elements of an array inside an object

trialObject : {
'color': ['red','blue'],
'size': ['s','m'],
'material': ['cotton']
}
// RECURSION FUNCTION TO MAKE COMBINATIONS
makeObjectVariants(selected){
let key = Object.keys(selected)
if(Object.keys(selected).length === 1){
return selected[key[0]];
} else {
var result = [];
var currentArray = selected[key[0]]
delete selected[key[0]]
var restObjects = this.makeObjectVariants(selected) // call function again
for(var i = 0; i < restObjects.length; i++){
for (var j = 0; j < currentArray.length; j++) {
result.push([restObjects[i] +','+ currentArray[j]]);
}
}
return result; // resultant array
}
}
// OUTPUT
0:["cotton,s,red"]
1:["cotton,s,blue"]
2:["cotton,m,red"]
3:["cotton,m,blue"]
// EXPECTED OUTPUT
[{'material':cotton,'size':s,'color':red},...]
I want the output to contain key value pairs so that the array elements can be recognized which group they fall into.
I am facing problem in adding keys to the elements generated because m unable to keep track of the object keys
If you can use ES6 (default parameters, spread operator, arrow function, ...), the following code do the job:
var trialObject = {
color: ['red','blue'],
size: ['s','m'],
material: ['cotton']
};
var result = buildCombinations(trialObject);
console.log(result);
function buildCombinations(trialObject , keys = Object.keys(trialObject ), keyIndex = 0 , subObj = {}, res = []) {
trialObject[keys[keyIndex]].forEach(element => {
subObj[keys[keyIndex]] = element;
keys[keyIndex + 1] ? buildCombinations(trialObject , keys, keyIndex + 1, subObj, res) : res.push({...subObj});
});
return res;
}

Categories

Resources