I am writing a client in Ract that receives streaming data representing objects from a back end. The client parses this data and dynamically builds the object as a javascript data structure (typically an object or an array).
The backend has a Timeseries datatype that consists of timestamp keys and arbitrary values. A Timeseries can have duplicate timestamp keys like so:
{
'2019-08-22T18:34:15.777927965Z' : 1,
'2019-08-22T18:34:15.777927965Z' : 2,
'2019-08-22T18:34:15.777927965Z' : 3,
}
This means that I cannot use a javascript object to build this datastructure in the client given that only the last key/value pair added will be stored since the keys are the same.
My solution was to collect this data in an array:
[
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
The problem is that I have been asked to display this data in key/value format the way a javascript object would be displayed.
I am using the react-json-tree npm package to dislpay all the objects I am constructing which just takes an object or array and formats it nicely with collapsable dropdown arrows in the UI (this is not essential).
What options do I have to turn my array of arrays in the code into a nicely formatted object like data structure in the UI?
TLDR:
How do I display an array like this:
[
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
As colon separated key/value pairs in the UI, like objects?
Ideally I could pass this data structure into a library like react-json-tree.
You can display your data in the following way, if you want them to be given as a list :
const data = [
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
const Renderer = () =>
<ul>
{data.map(([key, val], id) => <li key={id}>{key}; {val}</li>)}
</ul>;
ReactDOM.render(<Renderer/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<div id="root"/>
To display it using react-json-tree, how about wrapping your array within an object ?
const data = [
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
<JSONTree data={{log: data}} />
OR
const data = {
log : [
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
}
<JSONTree data={log} />
Related
I want to convert this:
[null, 1890, null, NGU]
...into this:
[[], [1890], [], [NGU]]
I've tried creating a new array and pushing values to it, but that just ends up looking the same. Honestly, I'm unsure of what to even call what I'm trying to create. Is it a two-dimensional array or an array of objects?
This is for a google app script and the documentation calls it a two-dimensional array of values.
var arr = [null, 1890, null, 'NGU']
var arr2d = arr.map(x => [x])
console.log(arr2d) // output --> [ [ null ], [ 1890 ], [ null ], [ 'NGU' ] ]
Is there any operation in Javascript just like [x for x in array] in python?
For example, I'm using javascript to reading a json file where there're dozens of (key, value) pairs needed to be handled(or transformed into other format). And I thought working in this way is stupid:
let transformed = []
for (let key in json){
transformed = [ /* doing some transform*/ ]
}
Is there anything like:
let transformed = [
lambda function1(key), lambda function2(value) for key, value in json
]
Thanks in advance.
The rough equivalent of Python's list comprehension is Array.map:
const myArray = [1, 2, 3]
const transformed = myArray.map((item) => item + 1)
// [2, 3, 4]
But your example is not about an array, but about an Object with keys and values. In Python, this would be a dict, and you'd use a dict comprehension along the lines of {function1(key): function2(value) for key, value in my_dict.items()}.
In JavaScript, you can turn such an object into an array with Object.entries, then perform the map, and finally transform it back into an object using Object.fromEntries:
const myObject = { a: 1, b: 2 }
const transformed = Object.fromEntries(Object.entries(myObject)
.map(([key, value]) => [key + 'x', value + 1]))
// { ax: 2, bx: 3 }
Note that fromEntries is fairly new and you might need to add a polyfill for it.
You can use a code likes this. You must use a function that handle operation on current single item.
const words = ['hello', 'bird', 'table', 'football', 'pipe', 'code'];
const capWords = words.forEach(capitalize);
function capitalize(word, index, arr) {
arr[index] = word[0].toUpperCase() + word.substring(1);
}
console.log(words);
// Expected output:
// ["Hello", "Bird", "Table", "Football", "Pipe", "Code"]
First of all, javascript does NOT support Associative Arrays. If you are used to them in Python, PHP, and other languages you need to do a little workaround in JS to achieve the same functionality.
The most common way to simulate an associative array is using an object.
let testObject = {name: "Color", value: "Red"};
And then you push every object into an array so you end up with something like this:
let testArray = [{name: "Color", value: "Red"}, {name: "Color", value: "Blue"}];
Once you have this array consisting of objects, you can use map function to go through every object in the array and do whatever you want with it.
testArray.map((item, index) => {
console.log("The value of "+index+". item is: "item.value);
})
You can use Array.map() function. It work pretty like Array.forEach() function
const numbers = [1, 2, 3, 4, 5]
let newArray = numbers.map((element) => {
return element * 2
})
console.log(newArray) // excepted : [ 2, 4, 6, 8, 10 ]
It can be reduce using
const numbers = [1, 2, 3, 4, 5]
let newArray = numbers.map(element => element * 2)
console.log(newArray) // excepted : [ 2, 4, 6, 8, 10 ]
For more informations, you can this documentation https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/map
It feels like push is behaving funny. Rather than just push to 1 index inside the forEach, it seems to be pushing to all 3 indexes. Am I missing something obvious?
let arrayToReduce = [ [ 1, 2, 3 ] ]
let reduced = arrayToReduce.reduce((arr, inner) => {
const copied = arr.slice()
inner.forEach((num, idx) => {
copied[idx].push(num)
})
return copied
}, Array(arrayToReduce[0].length).fill([]))
console.log(reduced)
Expected output: [[1], [2], [3]]
Actual output: [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
push isn't the culprit, it is fill.
You've created an array the same length as the original and then filled it with a value.
That value is an array.
The same array.
So when you push a value to copied[0] you get a reference to that array and put a value into it.
And when you push a value to copied[1] you get a reference to that same array and put another value into it.
let arr = [ [ 7, 3, 47 ] ]
let reduced = arr.flat().map(e=>[e])
console.log(reduced)
//output: [[7], [3], [47]]
if you want your Expected output : [[1], [2], [3]]
Simply return index instead of item in inner array
let arr = [ [ 7, 3, 47 ] ]
let reduced = arr.flat().map((e,i)=>[i+1])
console.log(reduced)
I am trying to define a function, merge, which, when given two sorted arrays containing numbers, returns a sorted array of the numbers from both lists.
merge([ 4, 5, 6 ], [ 1, 2, 3, 4 ]) => [ 1, 2, 3, 4, 4, 5, 6 ]
merge([ 4 ], [ 2, 5, 8 ]) => [ 2, 4, 5, 8 ]
merge([ 1, 2, 6 ], []) => [ 1, 2, 6 ]
This is my code:
function merge(arr1, arr2) {
return arr1.concat(arr2).sort(arr1, arr2);
}
While the output is correct, I am told -- from my studies, and its automated tests -- that this code is not in good style. It writes:
Does not handles two arrays of same length.
Doesn't handle shorter first array.
Doesn't handle shorter second array.
What is a better way I can write this code? What should I do better?
Your code looks ok, however the way you're using sort is incorrect.
One way to use sort is to supply a function that compares two values in the array, and returns a number (positive or negative) to dictate the sorting of those values. For more information on sort, see this article
Consider the following changes to your merge method:
function merge(arr1, arr2) {
return arr1.concat(arr2).sort(function(valueA, valueB) { return valueA - valueB; );
}
Other answers already give you the literal answer of how to make your code correct. However, it is possibly missing the point. The function that you described is used in building a "merge sort", a very important sorting algorithm, whose major advantage is that it only needs to read the input lists once, sequentially, resulting in complexity of O(N) per pass; this allows it to even sort things that can't fit into the memory. Your code does not do that - it relies on sort, which is O(N log(N)) each time you invoke your function, and it doesn't utilise the fact that both its inputs are already pre-sorted (which is a key requirement for merge sort).
The merge sort algorithm will take the first element from both lists, then append the smaller one. Then it compares the next element from that list with the other list's first element, and again takes the smaller one. Repeat until one list is exhausted, then append the rest of the surviving list. (You can find a more exhaustive explanation of the merge sort on the Wikipedia page).
Amadan's answer paid attention to the problem constraints and pointed out that this can be written in O(n) time. Essentially, when inputs are both sorted, the algorithm is the "merge" step in a merge sort. This is done in linear time and works in a very simple and pleasing manner: look at the first item of each list and take the smaller of the two until one or both lists are exhausted. Then, tack any remaining elements onto the result array and return it.
The other answers are fine and in good JS style, but are in O(n log n) time and ignore entirely that the arrays are pre-sorted without mention, which is almost certainly not the answer someone asking for this routine would be looking for.
Here's a merge step:
const merge = (a, b) => {
const result = [];
while (a.length && b.length) {
result.push(a[0] < b[0] ? a.shift() : b.shift());
}
return result.concat(a).concat(b);
};
console.log(merge([ 4, 5, 6 ], [ 1, 2, 3, 4 ])); // => [ 1, 2, 3, 4, 4, 5, 6 ]
console.log(merge([ 4 ], [ 2, 5, 8 ])); // => [ 2, 4, 5, 8 ]
console.log(merge([ 1, 2, 6 ], [])); // => [ 1, 2, 6 ]
This can also be done with indexes which preserves the original arrays and is faster, but a little uglier-looking.
Here's a benchmark at JSPerf.
Just concat the arrays and return after applying a simple sort function:
console.log(merge([4, 5, 6], [1, 2, 3, 4])); //[ 1, 2, 3, 4, 4, 5, 6 ]
console.log(merge([4], [2, 5, 8])); //[ 2, 4, 5, 8 ]
console.log(merge([1, 2, 6], [])); //[ 1, 2, 6]
function merge(a, b) {
return a.concat(b).sort((a, b) => a - b);
}
I'm using d3.js and nvd3.js to display some data from different datasets. One of the sets (A) contains the absolute number of orders, the other set (B) contains the number of orders from new customers, such that A >= B for every position. Example:
[{
key : 'orders',
values: [[1, 10], [2, 5], [3, 8], ...]
},{
key : 'orders by new customers',
values: [[1, 4], [2, 0], [3, 4], ...]
}]
I'd like to use a stacked multibar chart to display those series. In "Grouped" view, everything works nicely and I have both bars grouped beneath each other. However, when I switch to "Stacked" mode I was expecting, that the overall number does not change. It appeared that nv3d.js is then adding up both values and i get a new overall value.
Is there a way to change the calculation when switching to stacked mode? I was digging through the source code, but could not find a usable method to achieve this.
Thanks in advance!
If I understood your problem correctly, it would make more sense to restructure your data to make it conceptually match with bars being 'stacked' (which implies two values being added together), to something like this where:
orders = recurring orders + orders by new customers
[{
key : 'recurring orders',
values: [[0, 6], [0, 5], [0, 4], ...]
},{
key : 'orders by new customers',
values: [[1, 4], [2, 0], [3, 4], ...]
}]