Related
I want to print all even values in all object key end with odd value but the coding I made just now is only specified for arr1, arr3, and arr5. Can anyone suggest me how to fix 'let oddArr' method (maybe in loop) so that when I changed arr1 into arr7, the result would be the same.
var num = {
arr1 : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
arr2 : [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
arr3 : [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
arr4 : [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
arr5 : [41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
};
let oddArr = [...num.arr1, ...num.arr3, ...num.arr5] //need some correction here
let evenNum = oddArr.filter(number => number % 2 == 0);
console.log(evenNum.toString());
//help me fix 'let oddArr' (maybe in loop method) so that when I changed the object of the array (e.g: arr1 -> arr7) it would come out with the same result
//the result/output should be 2,4,6,8,10,22,24,26,28,30,42,44,46,48,50 based on var num
You can try like below using for in loop and it works with any last character as odd.
var num = {
arr1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
arr2: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
arr3: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
arr4: [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
arr7: [41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
};
let oddArr = [];
for (let key in num) {
if (key.charAt(key.length - 1) % 2 !== 0) {
oddArr = [...oddArr, ...num[key]];
}
}
let evenNum = oddArr.filter((number) => number % 2 === 0);
console.log(evenNum.toString());
You might want to use
let oddArr = Object.entries(num).filter( // filter key names
e => +e[0].replace("arr", '') % 2 !== 0 // replace "arr" and check if X in arrX is odd
).map(e => e[1]).flat() // merge values and flattern array
You can also make use of regex if the "arrX"-naming is not consistent:
+e[0].match(/\d+/) % 2 !== 0
See a working snippet below:
var num = {
arr1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
arr2: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
arr3: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
arr4: [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
arr5: [41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
};
let oddArr = Object.entries(num).filter(
e => +e[0].replace("arr", '') % 2 !== 0
).map(e => e[1]).flat()
let evenNum = oddArr.filter(number => number % 2 == 0);
console.log(evenNum.toString());
This also works.
var num = {
arr1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
arr2: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
arr3: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
arr4: [31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
arr5: [41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
arr6: [51, 52, 53, 55, 55, 56, 57, 58, 59, 60],
arr7: [61, 62, 63, 66, 65, 66, 67, 68, 69, 70],
};
var evenNums = Object.keys(num).filter((item) => {
itemNum = item.replace("arr", "");
return itemNum % 2 !== 0;
}).map((o) => num[o]).flat().filter((x) => x % 2 == 0);
console.log(evenNums);
I'm trying to write a function that, given an array and n, returns the array with elements repeating no more than n times. I cannot change the order of the array.
Below is the code I have so far. What is perplexing me is that it works for most elements in a given array, but not for some others. I'm trying to find a rhyme or reason for the elements for which the code does not work.
function deleteNth(arr,n){
arr.forEach(function (item, index) {
var count = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === item) {
count++;
while (count > n) {
var remove = arr.lastIndexOf(item);
arr.splice(remove, 1);
count--;
}
}
}
});
return arr;
}
var x = deleteNth([7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35,
35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41,
35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7,
2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10], 2);
console.log(x);
Currently returns this...
[7, 26, 21, 41, 43, 2, 26, 24, 10, 10, 10, 24, 35, 35, 43, 41, 7, 21,
41, 2, 43, 28]
But I should get this...
[7, 26, 21, 41, 43, 2, 26, 24, 10, 10, 24, 35, 35, 43, 41, 7, 21, 2,
28]
Any insight into where I'm going wrong would be sincerely appreciated.
The logic of where you places the while loop is wrong, you need to place it outside of the for loop.
function deleteNth(arr, n) {
arr.forEach(function(item, index) {
var count = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === item) {
count++;
}
}
while (count > n) {
var remove = arr.lastIndexOf(item);
arr.splice(remove, 1);
count--;
}
});
return arr;
}
var x = deleteNth([7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35,
35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41,
35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7,
2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10
], 2);
console.log(x);
Why? Because when you are doing your loop and you remove things from it, you shift things back down. So when you have two items side by side and you remove the first the second one shifts down one spot to fill what you just removed. The i does not change so you do not check the item that just filled the gap.
What would I do? I would just keep track of the items as I get to it and if I have not gone over the max append it.
function cleanUp (arr, max) {
const cnts = {} // keep track of what we find
return arr.reduce((a, i) => { // loop over the array index by index
cnts[i] = (cnts[i] || 0) + 1; // mark that I seen the number
if (cnts[i] <= max) { // check to see if we are under the max
a.push(i) //if we are, add it to an arry
}
return a // return the array for reduce
}, [])
}
console.log(cleanUp([7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35,
35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41,
35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7,
2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10], 2))
This code works:
function deleteNth(arr,n){
var rem = new Array(), new_arr = new Array();
arr.forEach(function (item, index) {
if(!rem[item]) rem[item]=0;
if(rem[item]<n){
new_arr.push(item);
rem[item]++;
}
});
return new_arr;
}
console.log(deleteNth([7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35, 35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41, 35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7, 2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10], 2));
All of your code is true. Just bring that while out of for loop.
function deleteNth(arr, n) {
arr.forEach(function(item, index) {
var count = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === item) {
count++;
}
}
while (count > n) {
var remove = arr.lastIndexOf(item);
arr.splice(remove, 1);
count--;
}
});
return arr;
}
var x = deleteNth([7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35,
35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41,
35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7,
2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10
], 2);
console.log(x);
I like Nina's filter (probably performs better as well) but you can also use reduce:
function deleteNth(arr,n){
return arr.reduce(
([result,map],item)=>{
const count = (map.get(item)||0)+1;
return [
//do not add if more than n of this item have been added already
(count<=n)?result.concat(item):result,
map.set(item,count)//set the new count for this item and return map
]
},
[[],new Map()]//initial value for result and map
)[0];
}
Here is an example using filter and a Map:
function deleteNth(arr,n){
const map = new Map();
return arr.filter(
item=>{
const count = (map.get(item)||0)+1;
map.set(item,count);
return (count<=n);
}
);
}
console.log(deleteNth([1,2,3,2,4,2,5], 2));
If you really want to do it in place, then this answer is not for you. (I think there are very good reasons to work with immutable data, but if you want to mutate, one of the other answers should do it.
Here's one solution that simply keeps a count of each item seen as you go, and filters out those we've seen too often:
const deleteNth = (arr, n) => {
const found = new Map()
return arr.filter(val => {
found.set(val, (found.get(val) || 0) + 1)
return found.get(val) <= n
})
}
const result = deleteNth([7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35, 35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41, 35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7, 2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10], 2)
console.log(result)
One other note: It might offer a nicer API if you choose:
deleteNth = (n) => (arr) => { /* ... */ }
This way you could pass just the repetition count and get back a new function which filters an array.
(Also, this does not sound like a good name for something that delete's all repetitions of a value after the nth one.)
For a fast mutating version, you could use a single while loop, a hash table for counting the items and an adjustment of the index if a splice happens.
function deleteNth(array, n) {
var counter = Object.create(null),
i = 0, v;
while (i < array.length) {
v = array[i];
if (!counter[v]) {
counter[v] = 0;
}
if (++counter[v] > n) {
array.splice(i, 1);
continue;
}
i++;
}
return array;
}
console.log(deleteNth([7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35, 35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41, 35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7, 2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10], 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
A better way is to use filter and return a new array.
function deleteNth(array, n) {
var counter = Object.create(null);
return array.filter(v => (counter[v] = (counter[v] || 0) + 1) <= n);
}
console.log(deleteNth([7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35, 35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41, 35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7, 2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10], 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am trying to manually set the length of a category axis. In detail I want the length of the x axis equal to the length of the y axis. So far I tried diverse layout settings from plotly manual without results.
var layout = {
width: 400,
height: 300,
plot_bgcolor: '#98ff6d',
};
var data = [{
z: [
[1, 20, 10, 12, 1, 1, 20, 10, 12, 1],
[24, 1, 12, 19, 0, 1, 20, 10, 12, 1],
[8, 1, 4, 12, 16, 1, 20, 20, 12, 0],
[1, 20, 10, 12, 1, 13, 20, 0, 12, 21],
[24, 1, 12, 19, 0, 1, 20, 10, 12, 1],
[8, 1, 4, 12, 16, 1, 20, 10, 1, 12],
[1, 20, 10, 12, 1, 1, 20, 10, 12, 14],
[24, 1, 12, 19, 0, 1, 20, 10, 12, 1],
[8, 13, 4, 12, 16, 1, 21, 20, 0, 18],
[1, 20, 0, 12, 1, 21, 65, 10, 12, 1],
[24, 1, 12, 19, 0, 1, 20, 10, 12, 1],
[8, 1, 4, 12, 16, 1, 20, 10, 15, 0],
[1, 20, 10, 12, 1, 1, 30, 10, 12, 14],
[24, 13, 12, 19, 0, 1, 20, 10, 12, 1],
[8, 1, 4, 12, 16, 1, 29, 1, 19, 31],
[1, 20, 10, 12, 1, 31, 0, 10, 12, 19],
[24, 1, 12, 19, 0, 1, 20, 10, 12, 1],
[8, 1, 4, 12, 16, 1, 20, 10, 11, 21],
[1, 0, 10, 12, 1, 1, 10, 10, 12, 21],
[24, 1, 0, 19, 0, 1, 20, 10, 12, 1],
[8, 1, 4, 12, 16, 1, 20, 1, 19, 36],
[1, 20, 10, 12, 1, 21, 21, 10, 12, 31],
[24, 1, 12, 19, 0, 1, 20, 10, 12, 1],
[8, 12, 4, 12, 16, 1, 21, 43, 12, 18],
[1, 20, 10, 12, 1, 1, 39, 10, 12, 13],
[24, 1, 12, 19, 0, 1, 20, 12, 2, 1],
[8, 1, 4, 12, 16, 1, 20, 10, 1, 11],
[1, 20, 10, 12, 1, 19, 38, 10, 12, 16],
[24, 12, 12, 19, 0, 1, 20, 10, 12, 1],
[8, 1, 4, 12, 16, 1, 29, 4, 12, 3],
[1, 20, 0, 12, 1, 1, 23, 10, 12, 11],
[24, 1, 12, 19, 0, 1, 20, 10, 12, 1],
[8, 19, 4, 12, 16, 1, 20, 10, 12, 19],
[1, 20, 10, 12, 1, 1, 24, 10, 12, 0],
[24, 1, 12, 19, 023, 1, 22, 10, 12, 1],
[8, 1, 41, 12, 16, 1, 20, 10, 12, 11]
],
x: ['T1', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'T8', 'T9', 'T10'],
y: ['Messung 1', 'Messung 2', 'Messung 3',
'Messung 4', 'Messung 5', 'Messung 6',
'Messung 7', 'Messung 8', 'Messung 9',
'Messung 10', 'Messung 11', 'Messung 12',
'Messung 13', 'Messung 14', 'Messung 15',
'Messung 16', 'Messung 17', 'Messung 18',
'Messung 19', 'Messung 20', 'Messung 21',
'Messung 22', 'Messung 23', 'Messung 24',
'Messung 25', 'Messung 26', 'Messung 27',
'Messung 28', 'Messung 29', 'Messung 30',
'Messung 31', 'Messung 32', 'Messung 33',
'Messung 34', 'Messung 35', 'Messung 36'
],
type: 'surface'
}];
Plotly.newPlot('plot', data, layout, {
displayModeBar: true,
displaylogo: false
});
#plot {
height: 100vh, width:100vw;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest compiled and minified plotly.js JavaScript -->
<script type="text/javascript" src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="plot"></div>
Give your layout Object a scene, and set your desired range on its axis, yaxis, and (if you like) zaxis properties. E.g.
var MIN_VAL = -100, MAX_VAL = 100;
var layout = {
scene:{
axis: {
nticks: 10,
range: [ MIN_VAL, MAX_VAL ]
},
yaxis: {
nticks: 10,
range: [ MIN_VAL, MAX_VAL ]
},
zaxis: {
nticks: 7,
range: [ MIN_VAL, MAX_VAL ]
},
aspectmode: "manual",
aspectratio: { x: 1, y: 1, z: 0.7 },
bgcolor : '#98ff6d'
},
autosize: false,
width: 400,
height: 300,
margin: { l: 0, r: 0, b: 50, t: 50, pad: 4 }
};
Plotly.newPlot('plot', data, layout);
Plotly has a working example (that shows the use of even more layout options) on CodePen.
I have an array that can be of any length. and need to split it into sections. The first section will be a length of 14, and there after a length of 16
var size1 = 14;
var size2 = 16;
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40];
var arrays = [];
if (a.length > 14){
for (i = 0; i < 14; i++) {
arrays.push(a.splice(0, size1));
}
for (i = 14 ; i < a.length; i++){
arrays.push(a.splice(0, size2));
}
} else {
arrays.push(a.splice(0, size1));
}
console.log(arrays);
However based on what I am doing my array keeps splitting only at 14. Can you advice on how I can do this?
Thank you
The solution using Array.prototype.slice() function:
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
size1 = 14,
size2 = 16,
arrays = [];
[0, size1, size2].forEach(function (v, i, arr) {
arrays.push((arr[i+1])? a.slice(v, v + arr[i+1]) : a.slice(arr[i-1] + v));
});
console.log(arrays);
You could use an array for the chunk length and a zero for the rest and map the chunks by keeping the length of the previous lengths.
It works for an arbitrary count of chunks.
var chunks = [14, 16, 0],
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
result = chunks.map((last => a => array.slice(last, a ? (last += a) : undefined))(0));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Edit: so, like this then?
var size1 = 14;
var size2 = 16;
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40];
var head = a.slice(0, size1);
var arrays = [head];
while (size1 < a.length){
arrays.push(a.slice(size1, Math.min(size1+size2, a.length)));
size1 += size2;
}
console.log(arrays)
You can try this with all dynamic array sizes, it will get you desired output.
Hope you were looking for this solution.
var size1 = 14;
var size2 = 16;
var flag=0;
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40];
var arrays = [];
var t=a.length/14;
while(a.length>0){
if (flag==0 && a.length > 14){
arrays.push(a.splice(0, size1));
flag=1;
} else if(a.length>=16){
arrays.push(a.splice(0, size2));
}
else{
arrays.push(a.splice(0, a.length));
}
}
console.log(arrays)
I am familiar with the kendoTooltip plugin and have worked with many other controls, and the typical approach for configuring the plugin does not appear to be working.
Using the sparkline chart, by default the tooltips are displaying just to the right of the cursor. Unfortunately, as you can see in this image, this renders any covered area of the sparkline unable to respond to hover input, meaning, you force the user out of the control and in again in order to see the other values.
You can try it out on Telerik's site.
I have tried passing in the config that works otherwise for the tooltip in other areas of Kendo UI, in this case, I've used position: "top" and applied it to the widget with the following:
$("#temp-log").kendoSparkline({
type: "column",
data: [
16, 17, 18, 19, 20, 21, 21, 22, 23, 22,
20, 18, 17, 17, 16, 16, 17, 18, 19, 20,
21, 22, 23, 25, 24, 24, 22, 22, 23, 22,
22, 21, 16, 15, 15, 16, 19, 20, 20, 21
],
tooltip: {
format: "{0} °C",
position: "top"
}
});
However, this option is not being applied, whereas some other properties are (such as format and visible).
Is there a way to change the position of the tooltip so it doesn't interfere with user interaction?
You can modify the tooltip's anchoring code:
Html target:
<span id="temp-log"></span>
Chart:
var s = $("#temp-log").kendoSparkline({
type: "column",
data: [
16, 17, 18, 19, 20, 21, 21, 22, 23, 22,
20, 18, 17, 17, 16, 16, 17, 18, 19, 20,
21, 22, 23, 25, 24, 24, 22, 22, 23, 22,
22, 21, 16, 15, 15, 16, 19, 20, 20, 21
],
tooltip: {
format: "{0} °C"
}
}).data("kendoSparkline");
This will only change the tooltip for this specific chart:
var templogHeight = $("#temp-log").height();
s._tooltip._slotAnchor = function(point, slot) {
var result = kendo.dataviz.SharedTooltip.fn._slotAnchor.call(this, point, slot);
return {
x: result.x,
y: result.y - templogHeight
};
};
(demo)
You could also do this for all sparkline charts by overriding the widget and changing the anchor code in the widget's init method.
The tooltip in sparkline charts doesn't accept a position.
Try http://dojo.telerik.com/#harsh/eNUkO
.k-tooltip {
margin-top:-40px;
margin-left:20px;
}
If you do not want the tooltip to be on top for other widgets create a class with these styles and add to k-tooltip element when a chart is hovered.
Or
http://dojo.telerik.com/#harsh/OyacA
Html:
<span id="sparkline-chart" class="sparkline"></span>
Js:
$("#sparkline-chart").kendoSparkline({
type: "column",
data: [
16, 17, 18, 19, 20, 21, 21, 22, 23, 22,
20, 18, 17, 17, 16, 16, 17, 18, 19, 20,
21, 22, 23, 25, 24, 24, 22, 22, 23, 22,
22, 21, 16, 15, 15, 16, 19, 20, 20, 21],
tooltip: {
format: "{0} °C"
}
});
$(".sparkline").on('mouseover', function () {
$('body').addClass('chart');
});
$(".sparkline").on('mouseout', function () {
$('body').removeClass('chart');
});
Css:
.chart .k-chart-tooltip
{
margin-top:-40px;
margin-left:20px;
}