I have a Sentence and also an array of clickable words from the sentence. The Array does not include the punctuation marks.
Here is a sentence
Into the trunk we put two poles and the can of worms and a sack of sandwiches and a thermos of water. “We’re going on a journey,” my father said. “To a secret place. We’ll catch the air! We’ll catch the breeze!”
Here is the structure of the clickable words. It's an array containing the indexes of where within the sentence the word begins and ends. This Array does not contain the punctuation marks in the sentence
Theu punctuation marks are not clickable.
"tokens": [
{
"position": [
0,
4
],
"value": "into"
},
{
"position": [
5,
8
],
"value": "the"
},
{
"position": [
9,
14
],
"value": "trunk"
},
{
"position": [
15,
17
],
"value": "we"
},
{
"position": [
18,
21
],
"value": "put"
},
{
"position": [
22,
25
],
"value": "two"
},
{
"position": [
26,
31
],
"value": "poles"
},
{
"position": [
32,
35
],
"value": "and"
},
{
"position": [
36,
39
],
"value": "the"
},
{
"position": [
40,
43
],
"value": "can"
},
{
"position": [
44,
46
],
"value": "of"
},
{
"position": [
47,
52
],
"value": "worms"
},
{
"position": [
53,
56
],
"value": "and"
},
{
"position": [
57,
58
],
"value": "a"
},
{
"position": [
59,
63
],
"value": "sack"
},
{
"position": [
64,
66
],
"value": "of"
},
{
"position": [
67,
77
],
"value": "sandwiches"
},
{
"position": [
78,
81
],
"value": "and"
},
{
"position": [
82,
83
],
"value": "a"
},
{
"position": [
84,
91
],
"value": "thermos"
},
{
"position": [
92,
94
],
"value": "of"
},
{
"position": [
95,
100
],
"value": "water"
},
{
"position": [
103,
108
],
"value": "we're"
},
{
"position": [
109,
114
],
"value": "going"
},
{
"position": [
115,
117
],
"value": "on"
},
{
"position": [
118,
119
],
"value": "a"
},
{
"position": [
120,
127
],
"value": "journey"
},
{
"position": [
130,
132
],
"value": "my"
},
{
"position": [
133,
139
],
"value": "father"
},
{
"position": [
140,
144
],
"value": "said"
},
{
"position": [
147,
149
],
"value": "to"
},
{
"position": [
150,
151
],
"value": "a"
},
{
"position": [
152,
158
],
"value": "secret"
},
{
"position": [
159,
164
],
"value": "place"
},
{
"position": [
166,
171
],
"value": "we'll"
},
{
"position": [
172,
177
],
"value": "catch"
},
{
"position": [
178,
181
],
"value": "the"
},
{
"position": [
182,
185
],
"value": "air"
},
{
"position": [
187,
192
],
"value": "we'll"
},
{
"position": [
193,
198
],
"value": "catch"
},
{
"position": [
199,
202
],
"value": "the"
},
{
"position": [
203,
209
],
"value": "breeze"
}
]
},
Here is my code that gets the clickable words
const getWordsFromTokens = tokens.reduce((words, token)=>{
let start = token.position[0]; //Start is the first character of the token value in the sentence
let end = token.position[1]; // end is the last character of the token value in the sentence
let diffrenceBetweenLastPositionAndFirst = end+(end-start);
/* You get punctuationMarks or any characters not in the Tokens by getting the string between
the end and diffrence between the end and start
*/
let punctuationMarks = content.substring(end, (diffrenceBetweenLastPositionAndFirst));
console.log(punctuationMarks);
words.push( content.substring(start, end)+punctuationMarks); //concat with any space of pucntuation mark after the word.
return words; //<- return this to be used in next round of reduce untill all words are
},[]);
Here is How I'm rendering the text
return (
<div>
<p> {
getWordsFromTokens.map((word, index)=>{
return <a href={'/word/' + word} > {word}</a>
})
}
</p>
</div>
)
Here is my problem, When I render the text, it does not look exactly like the original text. What is it that I could be doing wrong?
Here is how the final Result looks like
Into the the tr trunk we p we p put tw two po poles and and th the ca can of of w worms and and a a sack of of s sandwiches and a the and a a thermos of wat of w water. “We We’re goin going on a on a a journey,” my f my f father said. said. “T To a a secret place place. We’ We’ll catc catch the the ai air! W We’ll catc catch the the br breeze!”
What about a solution like this? I use a cursor to track the position inside the sentence.
const tokens = [{
"position": [
0,
4
],
"value": "into"
},
{
"position": [
5,
8
],
"value": "the"
},
{
"position": [
9,
14
],
"value": "trunk"
},
{
"position": [
15,
17
],
"value": "we"
},
{
"position": [
18,
21
],
"value": "put"
},
{
"position": [
22,
25
],
"value": "two"
},
{
"position": [
26,
31
],
"value": "poles"
},
{
"position": [
32,
35
],
"value": "and"
},
{
"position": [
36,
39
],
"value": "the"
},
{
"position": [
40,
43
],
"value": "can"
},
{
"position": [
44,
46
],
"value": "of"
},
{
"position": [
47,
52
],
"value": "worms"
},
{
"position": [
53,
56
],
"value": "and"
},
{
"position": [
57,
58
],
"value": "a"
},
{
"position": [
59,
63
],
"value": "sack"
},
{
"position": [
64,
66
],
"value": "of"
},
{
"position": [
67,
77
],
"value": "sandwiches"
},
{
"position": [
78,
81
],
"value": "and"
},
{
"position": [
82,
83
],
"value": "a"
},
{
"position": [
84,
91
],
"value": "thermos"
},
{
"position": [
92,
94
],
"value": "of"
},
{
"position": [
95,
100
],
"value": "water"
},
{
"position": [
103,
108
],
"value": "we're"
},
{
"position": [
109,
114
],
"value": "going"
},
{
"position": [
115,
117
],
"value": "on"
},
{
"position": [
118,
119
],
"value": "a"
},
{
"position": [
120,
127
],
"value": "journey"
},
{
"position": [
130,
132
],
"value": "my"
},
{
"position": [
133,
139
],
"value": "father"
},
{
"position": [
140,
144
],
"value": "said"
},
{
"position": [
147,
149
],
"value": "to"
},
{
"position": [
150,
151
],
"value": "a"
},
{
"position": [
152,
158
],
"value": "secret"
},
{
"position": [
159,
164
],
"value": "place"
},
{
"position": [
166,
171
],
"value": "we'll"
},
{
"position": [
172,
177
],
"value": "catch"
},
{
"position": [
178,
181
],
"value": "the"
},
{
"position": [
182,
185
],
"value": "air"
},
{
"position": [
187,
192
],
"value": "we'll"
},
{
"position": [
193,
198
],
"value": "catch"
},
{
"position": [
199,
202
],
"value": "the"
},
{
"position": [
203,
209
],
"value": "breeze"
}
];
const content = 'Into the trunk we put two poles and the can of worms and a sack of sandwiches and a thermos of water. “We’re going on a journey,” my father said. “To a secret place. We’ll catch the air! We’ll catch the breeze!"';
let cursorPosition = 0; // set a variable to track the position of cursor
const getWordsFromTokens = tokens.reduce((words, token) => {
let tokenStart = token.position[0]; //Start is the first character of the token value in the sentence
let tokenEnd = token.position[1]; // end is the last character of the token value in the sentence
let notWordBeforeThisWord = content.substring(cursorPosition, tokenStart); // get the non-word characters (spaces, punctuation) before the current word
let tokenValue = content.substring(tokenStart, tokenEnd);; // the word value
words.push({
type: 'non-word',
value: notWordBeforeThisWord
}, {
type: 'word',
value: tokenValue
}); //concat with any space of pucntuation mark after the word.
cursorPosition = tokenEnd; // update the cursor position
return words; // return this to be used in next round of reduce untill all words are
}, []);
getWordsFromTokens.forEach(item => {
const htmlToAppend = item.type === 'word' ?
`<a href='/word/${item.value}'>${item.value}</a>` :
item.value
document.getElementById('new-sentence').innerHTML += htmlToAppend;
})
const endOfSentence = content.substring(cursorPosition); // get all carachters (if any) after the last token
document.getElementById('new-sentence').innerHTML = document.getElementById('new-sentence').innerHTML + endOfSentence;
<p id='new-sentence'></p>
I think that using RegExp would make your life easier:
const content = `Into the trunk we put two poles and the can of worms and a sack of sandwiches and a thermos of water. "We're going on a journey," my father said. "To a secret place. We'll catch the air! We'll catch the breeze!`;
const result = content.match(/([\w'])+|([\.;,:-_?!"]+[\s"]*["]*)/gim);
console.log(result);
const punctuation = /[\.;,:\-_?!"]+/;
function App() {
return (
<div>
{result.map((w) =>
punctuation.test(w) ? w : <a href={`/word/${w}`}>{w + '\n'}</a>
)}
</div>
);
}
ReactDOM.render(<App/>, document.getElementById("root"))
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Related
I have an array like below:
const collection = [
{
"name": "Top1",
"data": [
{
"name": "shahnshah",
"data": [
{
"name": "test1",
"values": {
"val1": 876,
"val2": 3456
}
}
]
},
{
"name": "Alex",
"data": [
{
"name": "test1",
"values": {
"val1": 654,
"val2": 300
}
},
{
"name": "test2",
"values": {
"val1": 676,
"val2": 888
}
}
]
}
]
},
{
"name": "Top2",
"data": [
{
"name": "shahnshah",
"data": [
{
"name": "test1",
"values": {
"val1": 111,
"val2": 300
}
}
]
},
{
"name": "Alex",
"data": [
{
"name": "test1",
"values": {
"val1": 100,
"val2": 150
}
},
{
"name": "test2",
"values": {
"val1": 600,
"val2": 50
}
}
]
}
]
}
];
I'm trying to convert this data in a format where I can show this one in a table with total values for keys "val1", "val2" added in the top level of their corresponding top level keys ( i.e. name). The end result I'm expecting is something like this.
[
{
"name": "Top1",
// Only these two values will be extra
"val1": 2206, // "val1": 876 + "val1": 654 + "val1": 676
"val2": 4644, // "val1": 3456 + "val1": 300 + "val1": 888
"data": [
{
"name": "shahnshah",
"data": [
{
"name": "test1",
"values": {
"val1": 876,
"val2": 3456
}
}
]
}
]
},
{
// next object continued here
}
]
This way I want to able to show the sum of the values at the top and can eventually display this in a nested table.
const collection = [
{
"name": "Top1",
"data": [
{
"name": "shahnshah",
"data": [
{
"name": "test1",
"values": {
"val1": 876,
"val2": 3456
}
}
]
},
{
"name": "Alex",
"data": [
{
"name": "test1",
"values": {
"val1": 654,
"val2": 300
}
},
{
"name": "test2",
"values": {
"val1": 676,
"val2": 888
}
}
]
}
]
},
{
"name": "Top2",
"data": [
{
"name": "shahnshah",
"data": [
{
"name": "test1",
"values": {
"val1": 111,
"val2": 300
}
}
]
},
{
"name": "Alex",
"data": [
{
"name": "test1",
"values": {
"val1": 100,
"val2": 150
}
},
{
"name": "test2",
"values": {
"val1": 600,
"val2": 50
}
}
]
}
]
}
];
let newCollection=collection.reduce((a,c)=>{
c.val1=c.data.reduce((a1,c1)=>{ return a1+c1.data.reduce((aa,cc)=> aa+cc.values.val1,0);},0)
c.val2=c.data.reduce((a1,c1)=>{ return a1+c1.data.reduce((aa,cc)=> aa+cc.values.val2,0);},0)
a=[...a,c];
return a;
},[])
console.log(newCollection);
I have an flowchart input using jquery flowchart library like so:
Flowchart
I get the data representation as this:
{
"operators": {
"0": {
"properties": {
"title": "Start",
"inputs": {},
"outputs": {
"outs": {
"label": "Output (:i)",
"multiple": true
}
},
"class": "start-operator"
},
"top": 0,
"left": 0
},
"1": {
"properties": {
"title": "End",
"inputs": {
"ins": {
"label": "Input (:i)",
"multiple": true
}
},
"outputs": {},
"class": "end-operator"
},
"top": null,
"left": null
},
"37": {
"properties": {
"title": "CHROM",
"inputs": {
"ins": {
"label": "Input (:i)",
"multiple": true
}
},
"outputs": {
"output": {
"label": "Output"
}
}
},
"left": 300,
"top": 0
},
"38": {
"properties": {
"title": "CHROM",
"inputs": {
"ins": {
"label": "Input (:i)",
"multiple": true
}
},
"outputs": {
"output": {
"label": "Output"
}
}
},
"left": 580,
"top": 0
},
"39": {
"properties": {
"title": "REF",
"inputs": {
"ins": {
"label": "Input (:i)",
"multiple": true
}
},
"outputs": {
"output": {
"label": "Output"
}
}
},
"left": 920,
"top": 0
},
"40": {
"properties": {
"title": "REF",
"inputs": {
"ins": {
"label": "Input (:i)",
"multiple": true
}
},
"outputs": {
"output": {
"label": "Output"
}
}
},
"left": 300,
"top": 100
},
"41": {
"properties": {
"title": "REF",
"inputs": {
"ins": {
"label": "Input (:i)",
"multiple": true
}
},
"outputs": {
"output": {
"label": "Output"
}
}
},
"left": 300,
"top": 200
},
"42": {
"properties": {
"title": "REF",
"inputs": {
"ins": {
"label": "Input (:i)",
"multiple": true
}
},
"outputs": {
"output": {
"label": "Output"
}
}
},
"left": 620,
"top": 140
},
"43": {
"properties": {
"title": "POS",
"inputs": {
"ins": {
"label": "Input (:i)",
"multiple": true
}
},
"outputs": {
"output": {
"label": "Output"
}
}
},
"left": 740,
"top": 320
}
},
"links": {
"0": {
"fromOperator": "0",
"fromConnector": "outs",
"fromSubConnector": 0,
"toOperator": 37,
"toConnector": "ins",
"toSubConnector": 0,
"color": " #e53935"
},
"1": {
"fromOperator": "0",
"fromConnector": "outs",
"fromSubConnector": 1,
"toOperator": 40,
"toConnector": "ins",
"toSubConnector": 0,
"color": " #d81b60"
},
"2": {
"fromOperator": "0",
"fromConnector": "outs",
"fromSubConnector": 2,
"toOperator": 41,
"toConnector": "ins",
"toSubConnector": 0,
"color": " #8e24aa"
},
"3": {
"fromOperator": "0",
"fromConnector": "outs",
"fromSubConnector": 3,
"toOperator": 43,
"toConnector": "ins",
"toSubConnector": 0,
"color": " #5e35b1"
},
"4": {
"fromOperator": 37,
"fromConnector": "output",
"fromSubConnector": 0,
"toOperator": 38,
"toConnector": "ins",
"toSubConnector": 0,
"color": " #3949ab"
},
"5": {
"fromOperator": 40,
"fromConnector": "output",
"fromSubConnector": 0,
"toOperator": 42,
"toConnector": "ins",
"toSubConnector": 0,
"color": " #546e7a"
},
"6": {
"fromOperator": 41,
"fromConnector": "output",
"fromSubConnector": 0,
"toOperator": 42,
"toConnector": "ins",
"toSubConnector": 1,
"color": " #039be5"
},
"7": {
"fromOperator": 38,
"fromConnector": "output",
"fromSubConnector": 0,
"toOperator": 39,
"toConnector": "ins",
"toSubConnector": 0,
"color": " #00acc1"
},
"8": {
"fromOperator": 42,
"fromConnector": "output",
"fromSubConnector": 0,
"toOperator": 39,
"toConnector": "ins",
"toSubConnector": 1,
"color": " #00897b"
},
"9": {
"fromOperator": 39,
"fromConnector": "output",
"fromSubConnector": 0,
"toOperator": "1",
"toConnector": "ins",
"toSubConnector": 0,
"color": " #43a047"
},
"10": {
"fromOperator": 43,
"fromConnector": "output",
"fromSubConnector": 0,
"toOperator": "1",
"toConnector": "ins",
"toSubConnector": 1,
"color": " #7cb342"
}
},
"operatorTypes": {}
}
I want to use this for filtering data in tabulator so turn this into this:
[
{
"id": 1,
"pid": null
},
{
"id": 39,
"pid": 1
},
{
"id": 38,
"pid": 39
},
{
"id": 37,
"pid": 38
},
{
"id": 42,
"pid": 39
},
{
"id": 40,
"pid": 42
},
{
"id": 41,
"pid": 42
},
{
"id": 43,
"pid": 1
}
]
Then using this lines I turned into a tree:
const idMapping = data.reduce((acc, el, i) => {
acc[el.id] = i;
return acc;
}, {});
let root;
data.forEach(el => {
// Handle the root element
if (el.pid === null) {
root = el;
return;
}
// Use our mapping to locate the parent element in our data array
const parentEl = data[idMapping[el.pid]];
// Add our current el to its parent's `children` array
parentEl.children = [...(parentEl.children || []), el];
});
Here it is as a tree:
{
"id": 1,
"pid": null,
"children": [
{
"id": 39,
"pid": 1,
"children": [
{
"id": 38,
"pid": 39,
"children": [
{
"id": 37,
"pid": 38
}
]
},
{
"id": 42,
"pid": 39,
"children": [
{
"id": 40,
"pid": 42
},
{
"id": 41,
"pid": 42
}
]
}
]
},
{
"id": 43,
"pid": 1
}
]
}
Hovewer I want to simplify this further to just nested arrays of the id's. Like this:
[
1,
[
[
39,
[
[
38,
[
37
],
],
[
42,
[
40,
41
]
]
]
],
43
]
]
Question is, how to convert from tree to nested array?
You can use recursion to do this; leaf ids are passed upward without an array wrapper while interior node ids are wrapped in an array with a second element for their children.
const tree = { "id": 1, "pid": null, "children": [ { "id": 39, "pid": 1, "children": [ { "id": 38, "pid": 39, "children": [ { "id": 37, "pid": 38 } ] }, { "id": 42, "pid": 39, "children": [ { "id": 40, "pid": 42 }, { "id": 41, "pid": 42 } ] } ] }, { "id": 43, "pid": 1 } ] };
const objTreeToArrTree = node =>
node.children
? [node.id].concat([node.children.map(objTreeToArrTree)])
: node.id
;
console.log(JSON.stringify(objTreeToArrTree(tree), null, 2));
I see the code to create a Wilkinson Dot Plot in Vega-Lite:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A Wilkinson Dot Plot",
"height": 100,
"data": {
"values": [
10,11,11,11,14,15,17,
22,25,26,28,
33,33,33,34,37
]
},
"transform": [{
"window": [{"op": "rank", "as": "id"}],
"groupby": ["data"]
}],
"mark": {
"type": "circle",
"opacity": 1
},
"encoding": {
"x": {"field": "data", "type": "ordinal"},
"y": {"field": "id", "type": "ordinal", "axis": null, "sort": "descending"}
}
}
Creates a plot grouping the exact numbers, but I'd like the output to be by the first digit so really theres 7 vertical dots for 1, 4 vertical dots for 2, and 5 vertical dots for 3. I tried adding calculation: "str.map(x => x.charAt(0))" to the transform array so I could group by that, but was unsuccessful in my execution. Any ideas appreciated!
You were on the right track, except that calculate transforms cannot use arbitrary javascript code, but only the subset made available in Vega Expressions. So, for example, you could do something like this (vega editor):
{
"data": {
"values": [10, 11, 11, 11, 14, 15, 17, 22, 25, 26, 28, 33, 33, 33, 34, 37]
},
"transform": [
{"calculate": "floor(datum.data / 10)", "as": "data"},
{
"window": [{"op": "rank", "field": "data", "as": "id"}],
"groupby": ["data"]
}
],
"mark": {"type": "circle", "opacity": 1},
"encoding": {
"x": {"field": "data", "type": "ordinal"},
"y": {"field": "id", "type": "ordinal", "axis": null, "sort": "descending"}
}
}
const myJSON = {
"seller1": [
{
"product": "headphones",
"price": 23,
"weight": 1
},
{
"product": "earphone",
"price": 12,
"weight": 1
},
{
"product": "iPhone",
"price": 999,
"weight": 3
},
{
"product": "ipad",
"price": 399,
"weight": 4
}
],
"seller2": [
{
"product": "headphones",
"price": 25,
"weight": 1
},
{
"product": "earphone",
"price": 10,
"weight": 1
},
{
"product": "iPhone",
"price": 949,
"weight": 2
},
{
"product": "ipad",
"price": 449,
"weight": 3
}
]
}
I need to filter myJSON from a multi-select box where, if user selects product: iPhone and product: headphones, I need to display all the products that matches iPhone and headphones. In this case, myJSON will be
const myJSON = {
"seller1": [
{
"product": "headphones",
"price": 23,
"weight": 1
},
{
"product": "iPhone",
"price": 999,
"weight": 3
}
],
"seller2": [
{
"product": "headphones",
"price": 25,
"weight": 1
},
{
"product": "iPhone",
"price": 949,
"weight": 2
},
]
}
Now if the user selects different key, price: 449, myJSON should now be empty coz there is not property price: 449 in that anymore. But, if price: 23 then,
const myJSON = {
"seller1": [
{
"product": "headphones",
"price": 23,
"weight": 1
}
]
}
So for example, if user selects 3 items with same key(product), the we should show all the three items that match these 3 items from original json. Now when he selects a different key(price), then we should only filter from the previous result.
Any suggestion on how to implement this is much appreciated.
Given the follow Highcharts.Chart(options)
{
"chart": {
"type": "spline"
},
"title": {
"text": "",
"x": -20
},
"subtitle": {
"text": "",
"x": -20
},
"xAxis": [
"23 Jun",
"24 Jun",
"25 Jun",
"26 Jun",
"27 Jun",
"28 Jun",
"29 Jun"
],
"yAxis": {
"title": {
"text": ""
},
"plotLines": [
{
"value": 0,
"width": 1,
"color": "#808080"
}
]
},
"legend": {
"layout": "vertical",
"align": "right",
"verticalAlign": "middle",
"borderWidth": 0
},
"series": [
{
"name": "exposed",
"data": [
100,
200,
150,
130,
180,
200,
190
],
"dashStyle": "longdash"
},
{
"name": "converted",
"data": [
90,
80,
70,
75,
70,
80,
85
],
"dashStyle": "longdash"
},
{
"name": "engaged",
"data": [
30,
40,
35,
40,
48,
30,
33
],
"dashStyle": "longdash"
}
]
}
When I draw it with - $('#container').highcharts({...}) it prompts the error -
Uncaught Highcharts error #18: www.highcharts.com/errors/18
http://www.highcharts.com/errors/18
You can see it in - jsFiddle
What is wrong with that options format ?
Define a container in the jsFiddle
there is a problème with the x axis. You have to define an object not only an array. Ex
"xAxis": {categories: [
'23 Jun',
'24 Jun',
'25 Jun',
'26 Jun',
'27 Jun',
'28 Jun',
'29 Jun'
]}
do you expect somethink like this http://jsfiddle.net/x4YbZ/ ?