I'd like to create like this function in JS or TS but I couldn't.
Please teach me ...!
It is better if its function is made by functional-programming.
・Input type:Array(String)
・Output type:string or undefined
ex
Input
Result
["","0","3"]
"3"
["","",""]
undefined
["0","0","0"]
"0"
["1","3","2"]
"3"
Filter out all non-number elements from array.
Convert all string-number to Number type.
Use Math.max to get the largest value from array.
function getMaxValue(input) {
if (input.length) {
return Math.max.apply(null, input);
}
}
function sanitize(input) {
return input.filter(i => {
if (i === "" || i === null) {
return false;
}
return !isNaN(i);
}).map(i => Number(i));
}
let input1 = ["", "", "0"];
let input2 = [1, 3, 5];
let input3 = ["1", "", "5"];
let input4 = ["", "", ""];
let input5 = [undefined, null, "", "", "", "10"];
console.log(getMaxValue(sanitize(input1)));
console.log(getMaxValue(sanitize(input2)));
console.log(getMaxValue(sanitize(input3)));
console.log(getMaxValue(sanitize(input4)));
console.log(getMaxValue(sanitize(input5)));
You can try this.
const findMaximuminArray = (arr) => {
let max = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
if(max === "") return undefined;
return max;
}
You are using strings in your example, such as "1", but all of them contain digits actually, so I'm not sure what you're really trying to do.
However, here's a function that generates the results you want using lodash/fp:
_.compose(x => x ? x : undefined, _.max)
Whatever array argument you pass to it, it will get the maximum value and then convert it to undefined if it is falsy, as is the case for the empty string.
Here's the results generated for your input:
const fun = _.compose(x => x ? x : undefined, _.max);
const input = [["","0","3"],["","",""],["0","0","0"],["1","3","2"]]
_.forEach(x => console.log(fun(x)), input);
<script src="https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)"></script>
Related
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)
I have an array like below let's say
var myArray = ["1", "", "", "2","3","","","8"];
And I want to fill each " " value with previous not null value
According to that expectation should be like below
var myArray = ["1", "2", "2", "2","3","8","8","8"];
Here what I tried but didn't work
var myArray = ["1", "", "", "2","3","","","8"];
function myFunction() {
let currentEl=myArray [0];
let prevIndex=0;
fruits.map((e,a)=>{
if(e!="" && myArray[a-1]==""){
currentEl=e;
let interval=arrayGenerate(a-currentIndex-1,currentEl);
fruits.splice(currentIndex-1, currentEl+1, interval);
currentIndex=a;
}
})
}
function arrayGenerate(iteration,value){
let arr=[];
for(var i=0;i<iteration;i++){
arr.push(value);
}
return arr;
}
console.log(myArray)
You could map the new values and find the missing following value.
var array = ["1", "", "", "2", "3", "", "", "8"],
result = array.map((v, i, a) => v || a.find((w, j) => j > i && w));
console.log(result);
A solution with the same array, by looping from the end and storing the last value.
var array = ["1", "", "", "2", "3", "", "", "8"],
i = array.length,
value;
while (i--) {
if (array[i]) value = array[i];
else array[i] = value;
}
console.log(array);
I have done it like this. I loop over and awlays check the next element if its falsy and not the last element.
var myArray = ["1", "", "", "2","3","","","8"];
function fillArr(arr){
for(let i = arr.length - 1; i >= 0; i--){
if(!arr[i - 1] && i != arr.length){
arr[i - 1] = arr[i];
}
}
return arr;
}
let result = fillArr(myArray);
console.log(result);
You can make use of a stack array to stack indices of null items and then unstack them whenever you encounter a non null item in myArray. (stack is not a reserved keyword so you can call it anything) :
var stack = []
for(var i = 0; i < myArray.length; i++){
if(myArray[i] === "")
stack.push(i);
else if(stack.length !== 0){
for(var j = stack.length - 1 ; j > =0; j--){
myArray[stack[j]] = myArray[i];
stack.splice(j,1);
}
}
}
It's interesting how many different ways this can be done. Just another slightly ugly way to do the same thing:
const fill = (arr, lastVal) => (
arr.reverse()
.map(el => el.length > 0 ? lastVal = el : lastVal)
.reverse()
);
console.log(fill(["1", "", "", "2","3","","","8"]));
I want to extract only those strings which have unique characters, I have an array of strings:
var arr = ["abb", "abc", "abcdb", "aea", "bbb", "ego"];
Output: ["abc", "ego"]
I tried to achieve it using Array.forEach() method:
var arr = ["abb", "abc", "abcdb", "aea", "bbb", "ego"];
const filterUnique = (arr) => {
var result = [];
arr.forEach(element => {
for (let i = 0; i <= element.length; i++) {
var a = element[i];
if (element.indexOf(a, i + 1) > -1) {
return false;
}
}
result.push(element);
});
return result;
}
console.log(filterUnique(arr));
Want to know is any other way to achieve this task ?
Any suggestion.
I'd .filter by whether the size of a Set of the string is the same as the length of the string:
const filterUnique = arr => arr
.filter(str => new Set(str).size === str.length);
console.log(filterUnique(["abb", "abc", "abcdb", "aea", "bbb", "ego"]));
(a Set will not hold duplicate elements, so, eg, if 4 elements are put into a set and 2 are duplicates of others, the resulting size of the Set will be 2)
You can check by creating sets from strings also, a Set object will always have unique values.
var a = ["abb", "abc", "abcdb", "aea", "bbb", "ego"];
console.log(a.filter(v => v.length === new Set(v).size))
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);
Write a function countWords that, when given a string as an argument, returns an object where keys are the words in the string, and values are the number of occurrences of that word within the string:
function countWords(string){
string = string.split(" ");
var newObj = {};
for(var i = 0 ; i === newObj.string ; i++){
if(newObj['i'] === newObj[string]){
newObj[string[i]] = i ;
}
}
return newObj;
}
countWords("hello hello"); // => {"hello": 2}
countWords("Hello hello"); // => {"Hello": 1, "hello": 1}
countWords("The quick brown"); // => {"The": 1, "quick": 1, "brown": 1}
I realized since you do not need to count the index of the split string, you have to change the conditions from i < string.length to i === key value of of the objects. Why can't I access the strings with newObj.string?
You could do this with reduce() instead of for loop.
function countWords(string) {
return string.split(' ').reduce(function(r, e) {
r[e] = (r[e] || 0) + 1;
return r;
}, {})
}
console.log(countWords("hello hello"))
console.log(countWords("Hello hello"))
console.log(countWords("The quick brown"))
With for loop your code could go like this.
function countWords(string) {
var string = string.split(" ");
var newObj = {};
for (var i = 0; i < string.length; i++) {
newObj[string[i]] = (newObj[string[i]] || 0) + 1
}
return newObj;
}
console.log(countWords("hello hello"));
console.log(countWords("Hello hello"));
console.log(countWords("The quick brown"));
function countWords(string){
return string
.split(" ")
.reduce((acc, curr) => {
if (curr in acc) {
acc[curr]++
} else {
acc[curr] = 1
}
return acc
}, {})
}
console.log(countWords("hello hello"));
console.log(countWords("Hello hello"));
console.log(countWords("The quick brown"));
You can do it in the following way by using the hasOwnProperty function to check if a property exists in the JavaScript Object, if it does increment the count and if it doesn't then initialize the count to 1.
function countWords(data) {
var words = data.split(" ");
var item = {};
for (var i = 0; i < words.length; i++) {
var prop = words[i];
item.hasOwnProperty(prop) ? item[prop] ++ : item[prop] = 1;
}
console.log(item);
return item;
}
countWords("hello hello"); // => {"hello": 2}
countWords("Hello hello"); // => {"Hello": 1, "hello": 1}
countWords("The quick brown"); // => {"The": 1, "quick": 1, "brown": 1}
newObj[string[i]] = (newObj[string[i]] || 0) + 1
according to my understanding this statement is used to check for duplicity
suppose you crated an empty object and then stored the key value pair in it by using this statement "(newObj[string[i]] || 0) + 1" you are checking if the default value of the key is zero if its zero you then increment its value by 1 if there are multiple value for the same key by doing this you can get the unique value in the array
Example
const uniqueValues = arr => {
let newObj = {}
for (let val of arr){
newObj[val] = [newObj || 0] + 1;
}
return (Object.keys(newObj).length);
}
uniqueValues([1,1,1,1,1,2]);