Javascript, getting past values for an array of objects - javascript

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)

Related

Get dates from array and disable those dates from calendar that repeat more than twice

I want to get dates from array which are repeated 3 times so I can disable those dates from calendar.
function disbaleDate() {
const arr = [
"1/6/2022",
"12/6/2022",
"4/6/2022",
"6/6/2022",
"1/6/2022",
"1/6/2022",
];
const increment = [];
for (let i = 1; i < arr.length; i++) {
for (let j = 0; j < i; j++) {
if (arr[j] === arr[i]) {
increment.push(arr[i]);
}
}
}
console.log(increment);
}
disbaleDate();
const disable = () => {
const arr = [
"1/6/2022",
"12/6/2022",
"4/6/2022",
"6/6/2022",
"1/6/2022",
"1/6/2022",
];
let data =[];
data = arr.filter((el, i) => i !== arr.indexOf(el) )
let result = data.filter((el,i) => i ===data.indexOf(el))
return result;
}
console.log(disable())
Ok, updating my answer
// reducer willproduce an object with the date as the key, and the amount repeated as the value
const countRepeated = arr.reduce((a, c) => {
if (a[c]) {
a[c] = a[c] + 1;
return a;
}
a[c] = 1;
return a;
}, {})
// will filter those whose values are greater than 2
return Object.keys(countRepeated).filter( date => date > 2)
function disableDate() {
const arr = ["1/6/2022", "12/6/2022", "4/6/2022", "6/6/2022", "1/6/2022", "1/6/2022",];
const backendData = ["12/12/2022", "12/6/2021", "14/6/2022", "16/6/2022", "1/6/2022", "11/6/2022",];
const increment = [];
if (backendData.length > 0) {
for (let i = 0; i < backendData.length; i++) {
if (arr.includes(backendData[i])) {
increment.push(backendData[i]);
}
}
}
console.log(increment);
}
disableDate();

Javascript nested array: halve items and sum them up

I'm trying to create a function which returns me halve the data sumed up. I was able to do it on a non-nested Array but failing on the nested Array. I get the error Cannot read properties of undefined (reading 'push').
How the returned data should look like:
var data = [{"Key":1,"values":[
{"LastOnline":"21-11-29","Value":2},
{"LastOnline":"21-12-01","Value":2},
{"LastOnline":"21-12-03","Value":2}
]}];
What I have right now:
var data = [{"Key":1,"values":[
{"LastOnline":"21-11-28","Value":1},
{"LastOnline":"21-11-29","Value":1},
{"LastOnline":"21-11-30","Value":1},
{"LastOnline":"21-12-01","Value":1},
{"LastOnline":"21-12-02","Value":1},
{"LastOnline":"21-12-03","Value":1},
]}];
function halveMonth(data){
var newData = [];
var temp = [{"key":data.key,"values":[{}]}];
// sum 2 togheter
for(var i=1;i<data.values.length;i++){
if(data.values[i]){
temp.values[i].push({"LastOnline":data.values[i].LastOnline, "Value":(data.values[i].Value + data.values[[i-1]].Value)});
}
}
for(var i=0;i<temp.values.length;i++){
if(i % 2 == 0){
newData.push(temp.values[i]);
}
}
return newData;
}
console.log(halveMonth(data));
JS variables are case sensitive. Keep the key consistent everywhere. If you don't plan to use reduce here is the solution.
var data = [{"key":1,"values":[
{"LastOnline":"21-11-28","Value":1},
{"LastOnline":"21-11-29","Value":1},
{"LastOnline":"21-11-30","Value":1},
{"LastOnline":"21-12-01","Value":1},
{"LastOnline":"21-12-02","Value":1},
{"LastOnline":"21-12-03","Value":1},
]}];
function halveMonth(data){
let newData = []
for (let i = 0; i < data.length; i++) {
let temp = {"key":data[i].key,"values":[]}
for (let j = 0; j < data[i].values.length; j += 2) {
const res = (j+1===data[i].values.length) ? data[i].values[j].Value : data[i].values[j].Value + data[i].values[j+1].Value
temp.values.push({"LastOnline":(j+1===data[i].values.length)?data[i].values[j].LastOnline:data[i].values[j+1].LastOnline,"Value":res});
}
newData.push(temp);
}
return newData
}
console.log(halveMonth(data));
The variable data you declare at the first line of your snippet is an array. So you can't do data.values. You first need to indicate which index of your array you want to read. In this case : data[0].values
First things first, you data is itself an array - so assuming your real data has more than 1 element you'll need to do the same thing for each one.
It's helpful to start off with a method which does the work on just 1 element
const justASingle = {"Key":1,"values":[{"LastOnline":"21-11-28","Value":1},{"LastOnline":"21-11-29","Value":1},{"LastOnline":"21-11-30","Value":1},{"LastOnline":"21-12-01","Value":1},{"LastOnline":"21-12-02","Value":1},{"LastOnline":"21-12-03","Value":1}]};
function halveMonthSingle(data) {
return {
...data,
values: data.values.reduce((acc, item, idx) => {
if ((idx % 2) != 0)
acc.push({
...item,
Value: data.values[idx - 1].Value + item.Value
})
return acc;
}, [])
}
}
console.log(halveMonthSingle(justASingle))
Once you have that you can just use map do do it for every element
const data = [{"Key":1,"values":[{"LastOnline":"21-11-28","Value":1},{"LastOnline":"21-11-29","Value":1},{"LastOnline":"21-11-30","Value":1},{"LastOnline":"21-12-01","Value":1},{"LastOnline":"21-12-02","Value":1},{"LastOnline":"21-12-03","Value":1}]}];
function halveMonthSingle(data) {
return {
...data,
values: data.values.reduce((acc, item, idx) => {
if ((idx % 2) != 0)
acc.push({
...item,
Value: data.values[idx - 1].Value + item.Value
})
return acc;
}, [])
}
}
const result = data.map(halveMonthSingle)
console.log(result)
I would use reduce - saves me from trying to figure out why your two loops do not work other than data.values should be data[0].values
var data = [{"Key":1,"values":[{"LastOnline":"21-11-28","Value":1},{"LastOnline":"21-11-29","Value":1},{"LastOnline":"21-11-30","Value":1},{"LastOnline":"21-12-01","Value":1},{"LastOnline":"21-12-02","Value":1},{"LastOnline":"21-12-03","Value":1},]}];
const newArr = data.slice(0); // to not mutate original
newArr[0].values = data[0].values.reduce((acc,item,i) => {
if (i%2 !== 0) { // every second
acc.push(data[0].values[i]); // push the item
acc[acc.length-1].Value += data[0].values[i-1].Value; // add the first
}
return acc
},[])
console.log(newArr)
This works too. I basically did your idea, skipping the temp array and merging the two steps into one.
const data = [{"Key":1,"values":[
{"LastOnline":"21-11-28","Value":1},
{"LastOnline":"21-11-29","Value":1},
{"LastOnline":"21-11-30","Value":1},
{"LastOnline":"21-12-01","Value":1},
{"LastOnline":"21-12-02","Value":1},
{"LastOnline":"21-12-03","Value":1},
]}];
function halveMonth(data) {
const newData = [];
newData.push({
Key: data[0].Key,
values: []
});
for(let i = 0; i < data[0].values.length; i++){
if (i % 2 !== 0) {
newData[0].values.push({
LastOnline: data[0].values[i].LastOnline,
Value: data[0].values[i].Value + data[0].values[i-1].Value
});
}
}
return newData;
}
console.log(halveMonth(data));

How to - Improving my code performance to get unique value from array - Javascript

my code speed performance very slow when to get unique value from array that existing 5000 users data.
There is my code below which has two conditions:
First, to get unique value
Second, to check phone number is null or not, given preference to users data that existing phone number/s.
var arr = [
["Wong", ""],
["Wong", "0143213123"],
["Ali", "0177213123"],
["Ali", "0177213123, 0124545345"],
["Ali", ""],
["Imran", "0133454335"]
];
function uniq(arr) {
var seen = [];
for (i = 0; i < arr.length; i++) {
var a = arr[i][0];
var a2 = arr[i][1];
var c = true;
for (x = 0; x < seen.length; x++) {
var b = seen[x][0];
var b2 = seen[x][1];
if (b == a) {
c = false;
if ((b2.trim() == '' || b2.indexOf(',') == -1) && (a2.trim() != '')) {
seen[x][1] = a2.trim();
break;
}
break;
}
}
if (c == true) {
seen.push(arr[i]);
}
}
return seen;
}
Result, after code executed:
var arr = uniq(arr);
console.log(arr);
[
["Wong", "0143213123"],
["Ali", "0177213123, 0124545345"],
["Imran", "0133454335"]
];
In jsfiddle here
You could do something like this with reduce and store data in one object for each name.
var arr = [["Wong",""], ["Wong", "0143213123"], ["Ali", "0177213123"], ["Ali", "0177213123, 0124545345"], ["Ali", ""], ["Imran", "0133454335"]];
var uniq = arr.reduce((r, [name, number]) => {
if(!r[name] || number.trim().length) r[name] = number;
return r;
}, {});
console.log(Object.entries(uniq))

How to find the most duplicate "values" in javascript array?

my question is actually similar to: Extracting the most duplicate value from an array in JavaScript (with jQuery)
I Found this but it always return one value only which is 200.
var arr = [100,100,200,200,200,300,300,300,400,400,400];
var counts = {}, max = 0, res;
for (var v in arr) {
counts[arr[v]] = (counts[arr[v]] || 0) + 1;
if (counts[arr[v]] > max) {
max = counts[arr[v]];
res = arr[v];
}
}
console.log(res + " occurs " + counts[res] + " times");
pls help me to return values not just one...
The result is should like this:
200,300,400
.
pls help thank you!
You have to iterate your counts to find the max occurred result.
var arr = [100,100,200,200,200,300,300,300,400,400,400];
var counts = {}, max = 0, res;
for (var v in arr) {
counts[arr[v]] = (counts[arr[v]] || 0) + 1;
if (counts[arr[v]] > max) {
max = counts[arr[v]];
res = arr[v];
}
}
var results = [];
for (var k in counts){
if (counts[k] == max){
//console.log(k + " occurs " + counts[k] + " times");
results.push(k);
}
}
console.log(results);
Create a Object iterating the arry containing the indexes of most repeated values, like below
var arr = [100,100,200,200,200,300,300,300,400,400,400];
valObj = {}, max_length = 0, rep_arr = [];
arr.forEach(function(el,i){
if(valObj.hasOwnProperty(el)){
valObj[el] += 1;
max_length = (valObj[el] > max_length) ? valObj[el] : max_length
}
else{
valObj[el] = 1;
}
});
Object.keys(valObj).forEach(function(val){
(valObj[val] >= max_length) && (rep_arr.push(val))
});
console.log(rep_arr);
After the object is created with key as array value and value as array indexes of that value, you can play/parse that. Hope this helps.
Iterating an array using for..in is not a good idea. Check this link for more information.
Hopefully below snippet will be useful
var arr = [100, 100, 200, 200, 200, 300, 300, 300, 400, 400, 400];
//Use a reduce fuction to create an object where 100,200,300
// will be keys and its value will the number of times it has
//repeated
var m = arr.reduce(function(i, v) {
if (i[v] === undefined) {
i[v] = 1
} else {
i[v] = i[v] + 1;
}
return i;
}, {});
// Now get the maximum value from that object,
//getMaxRepeated will be 3 in this case
var getMaxRepeated = Math.max(...Object.values(m));
//An array to hold elements which are repeated 'getMaxRepeated' times
var duplicateItems = [];
// now iterate that object and push the keys which are repeated
//getMaxRepeated times
for (var keys in m) {
if (m[keys] === getMaxRepeated) {
duplicateItems.push(keys)
}
}
console.log(duplicateItems)
The following would do the trick assuming that all items in arr are numbers:
//added some numbers assuming numbers are not sorted
var arr = [300,400,200,100,100,200,200,200,300,300,300,400,400,400];
var obj = arr.reduce(//reduce arr to object of: {"100":2,"200":4,"300":4,"400":4}
(o,key)=>{//key is 100,200, ... o is {"100":numberOfOccurrences,"200":numberOf...}
o[key] = (o[key])?o[key]+1:1;
return o;
},
{}
);
// obj is now: {"100":2,"200":4,"300":4,"400":4}
//create an array of [{key:100,occurs:2},{key:200,occurs:4}...
var sorted = Object.keys(obj).map(
key=>({key:parseInt(key),occurs:obj[key]})
)//sort the [{key:100,occurs:2},... by highest occurrences then lowest key
.sort(
(a,b)=>
(b.occurs-a.occurs===0)
? a.key - b.key
: b.occurs - a.occurs
);
console.log(
sorted.filter(//only the highest occurrences
item=>item.occurs===sorted[0].occurs
).map(//only the number; not the occurrences
item=>item.key
)
);
Try as following ==>
function getDuplicate( arr ){
let obj = {}, dup = [];
for(let i = 0, l = arr.length; i < l; i++){
let val = arr[i];
if( obj[val] /**[hasOwnProperty]*/ ) {
/**[is exists]*/
if(dup.find(a => a == val) ) continue;
/**[put Unique One]*/
dup.push(val);
continue;
};
/**[hold for further use]*/
obj[val] = true;
}
return dup;
};
Use ==>
getDuplicate([100,100,200,200,200,300,300,300,400,400,400]);
Try the following:
var candles = [100,100,200,200,200,300,300,300,400,400,400];
let tempArray = {}
for (let index = 0; index <= (candles.length - 1); index++) {
let valueToCompare = candles[index];
if (tempArray[valueToCompare]) {
tempArray[valueToCompare] = tempArray[valueToCompare] + 1;
} else {
tempArray[valueToCompare] = 1;
}
}
let highestValue;
Object.values(tempArray).forEach(item => {
if (highestValue === undefined) highestValue = item;
if (highestValue < item) highestValue = item;
});
console.log(highestValue);

String split and count the number of occurrences and also

I have a string
var stringIHave = "Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$";
How to get the count of the number of occurrences of each entry, The occurrence I get, is from a JSON like Java = 8 and etc...
First of all you need to split your srting to array:
var keywordsArr = stringIHave.split( '$$' );
then you need to have an object for example to store counts:
var occur = {};
and then just create simple for loop to count all occurrences:
for( var i = 0; i < keywordsArr.length; i++ ) {
occur[ keywordsArr[ i ] ] = ( occur[ keywordsArr[ i ] ] || 0 ) + 1;
}
now your object occur will have names as keys and count as values.
See jsFiddle demo.
Also as you have at end of your string $$ you maybe will need to remove last item from keywordsArr so just do after split function call:
keywordsArr.pop();
See demo without last element.
So final code will be like:
var stringIHave = "Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$",
keywordsArr = stringIHave.split( '$$' ),
occur = {};
keywordsArr.pop();
for( var i = 0; i < keywordsArr.length; i++ ) {
occur[ keywordsArr[ i ] ] = ( occur[ keywordsArr[ i ] ] || 0 ) + 1;
}
for( var key in occur ) {
document.write( key + ' - ' + occur[key] + '<br/>' );
} ​
I'd suggest the following:
function stringCount(haystack, needle) {
if (!needle || !haystack) {
return false;
}
else {
var words = haystack.split(needle),
count = {};
for (var i = 0, len = words.length; i < len; i++) {
if (count.hasOwnProperty(words[i])) {
count[words[i]] = parseInt(count[words[i]], 10) + 1;
}
else {
count[words[i]] = 1;
}
}
return count;
}
}
console.log(stringCount("Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$", '$$'));
​
JS Fiddle demo.
References:
Object.hasOwnProperty().
parseInt().
String.split().
It's not entirely clear what final objective is. Following creates an object from string that looks like
Object created:
{
"Java": 8,
"jQuery": 4,
"Hibernate": 1,
"Spring": 1,
"Instagram": 1
}
JS:
var str = 'Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$';
var arr = str.split('$$')
var obj = {};
for (i = 0; i < arr.length; i++) {
if (arr[i] != '') {
if (!obj[arr[i]]) {
obj[arr[i]] = 0;
}
obj[arr[i]]++;
}
}
You can loop over the object to get all values or simply look up one value
var jQueryOccurences= obj['jQuery'];
DEMO: http://jsfiddle.net/25hBV/1/
Now a days you can do
const str = "Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$";
var result = str.split("$$").reduce(function(acc, curr) {
curr && (acc[curr] = (acc[curr] + 1) || 1);
return acc
}, {});
console.log(result);
Split the string into an array, and putting the array into an object takes care of duplicates and counts occurences as key/value pairs in the object, see fiddle!
var stringIHave = "Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$",
s = stringIHave.split('$$');
obj = {};
for (var i=s.length; i--;) {
obj[s[i]] = (s[i] in obj) ? obj[s[i]]+1 : 1;
}
// obj.Java == 8
FIDDLE
If you want it short and sweet:
// variable declarations
var arParts = stringIHave.match(/\w+/g),
result = {},
i = 0,
item;
// Copy the array to result object
while (item = arParts[i++]) result[item] = (result[item] || 0 ) + 1;
demo

Categories

Resources