Flatten an nested array of objects using Lodash - lodash

My object looks like this:
const features = [{
'name': 'feature1', 'tags':
[{'weight':10, 'tagName': 't1'},{'weight':20, 'tagName': 't2'}, {'weight':30, 'tagName': 't3'}]
},
{
'name': 'feature2', 'tags':
[{'weight':40, 'tagName': 't1'}, {'weight':5, 'tagName':'t2'}, {'weight':70, 'tagName':'t3'}]
},
{
'name': 'feature3', 'tags':[
{'weight':50, 'tagName': 't1'}, {'weight':2, 'tagName': 't2'}, {'weight':80, 'tagName': 't3'}]
}]
I would like my output to look something like this:
const features = [{'name':'feature1', 'weight':10, 'tagName':'t1'},
{'name':'feature1', 'weight':20, 'tagName':'t2'}, ...
{'name':'feature3', 'weight':80, 'tagName':'t3'}]
I tried to merge and the flatten but it does not work.
Update 1
I tried this:
let feat = features;
results = []
_.each(feat, (item) => {
console.log(item);
results.push(_.flatten(_.pick(item.tags, 'weight'))); // pick for certain keys.
}
Update 2
This solved my problem
_.each(features, (item) => {
_.each(item.tags, (itemTag) => {
results.push({'name':item.name, 'weight':itemTag.weight, 'tagName':itemTag.tagName})})})
But I want to know if there is a more lodash way to do this!

The approach below uses flatMap to flatten tags acquired through map. Finally, use the spread operator to assign the values from tag and the feature's name.
const result = _.flatMap(features, ({ name, tags }) =>
_.map(tags, tag => ({ name, ...tag }))
);
const features = [{
'name': 'feature1',
'tags': [{
'weight': 10,
'tagName': 't1'
}, {
'weight': 20,
'tagName': 't2'
}, {
'weight': 30,
'tagName': 't3'
}]
},
{
'name': 'feature2',
'tags': [{
'weight': 40,
'tagName': 't1'
}, {
'weight': 5,
'tagName': 't2'
}, {
'weight': 70,
'tagName': 't3'
}]
},
{
'name': 'feature3',
'tags': [{
'weight': 50,
'tagName': 't1'
}, {
'weight': 2,
'tagName': 't2'
}, {
'weight': 80,
'tagName': 't3'
}]
}
];
const result = _.flatMap(features, ({ name, tags }) =>
_.map(tags, tag => ({ name, ...tag }))
);
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Here's a plain javascript solution that uses Array#reduce and Array#map with the help of Array#concat to flatten the array.
const result = features.reduce(
(result, { name, tags }) => result
.concat(tags.map(tag => ({ name, ...tag }))),
[]
);
const features = [{
'name': 'feature1',
'tags': [{
'weight': 10,
'tagName': 't1'
}, {
'weight': 20,
'tagName': 't2'
}, {
'weight': 30,
'tagName': 't3'
}]
},
{
'name': 'feature2',
'tags': [{
'weight': 40,
'tagName': 't1'
}, {
'weight': 5,
'tagName': 't2'
}, {
'weight': 70,
'tagName': 't3'
}]
},
{
'name': 'feature3',
'tags': [{
'weight': 50,
'tagName': 't1'
}, {
'weight': 2,
'tagName': 't2'
}, {
'weight': 80,
'tagName': 't3'
}]
}
];
const result = features.reduce(
(result, { name, tags }) => result
.concat(tags.map(tag => ({ name, ...tag }))),
[]
);
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

Related

Echarts datazoom with grid of 4 charts

I have an eChart grid layout with 4 stacked bar charts and cannot figure out how to assign datazoom (nor have I found any examples of this online).
When I place the datazoom before the series, I DO get a zoom controller but only on one of the charts...
dataZoom: [{type: 'inside', start: 50, end: 100},
{start: 50, end: 100 }
}],
series: [{type: 'scatter'...
I won't post code for now (it's large) in hopes that someone can just tell me where to put the datazoom node.
I have no idea why you charts not working. Without example and with complex data you need to call fortune-teller only. In general datazoom can be easily attached to series.
var myChart = echarts.init(document.getElementById('main'));
var option = {
xAxis: [{
type: 'category',
gridIndex: 0
},
{
type: 'category',
gridIndex: 1
}
],
yAxis: [{
gridIndex: 0
},
{
gridIndex: 1
}
],
dataset: {
source: [
['product', '2012', '2013', '2014', '2015', '2016', '2017'],
['Matcha Latte', 41.1, 30.4, 65.1, 53.3, 83.8, 98.7],
['Milk Tea', 86.5, 92.1, 85.7, 83.1, 73.4, 55.1],
['Cheese Cocoa', 24.1, 67.2, 79.5, 86.4, 65.2, 82.5],
['Walnut Brownie', 55.2, 67.1, 69.2, 72.4, 53.9, 39.1]
]
},
grid: [{
bottom: '55%'
},
{
top: '55%'
}
],
series: [{
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 1,
encode: {
x: 'product',
y: '2012'
}
}, {
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 1,
encode: {
x: 'product',
y: '2013'
}
}, {
type: 'bar',
stack: 'st1',
encode: {
x: 'product',
y: '2014'
}
}, {
type: 'bar',
stack: 'st1',
encode: {
x: 'product',
y: '2015'
}
}],
dataZoom: [{
type: 'slider',
show: true,
xAxisIndex: [0, 1],
start: 1,
end: 70
},
{
type: 'inside',
xAxisIndex: [0, 1],
start: 1,
end: 35
},
],
};
myChart.setOption(option);
<div id="main" style="width: 600px;height:400px;"></div>
<script src="https://cdn.jsdelivr.net/npm/echarts#4.9.0/dist/echarts.min.js"></script>

React Native state is not getting updated

I want to update state on button click
this.state = {
legend: {
enabled: true,
textSize: 14,
form: 'CIRCLE',
horizontalAlignment: "RIGHT",
verticalAlignment: "CENTER",
orientation: "VERTICAL",
wordWrapEnabled: true
},
data: {
dataSets: [{
values: [{value: 45, label: 'Sandwiches'},
{value: 21, label: 'Salads'},
{value: 15, label: 'Soup'},
{value: 9, label: 'Beverages'},
{value: 15, label: 'Desserts'}],
label: 'Pie dataset',
}],
},
highlights: [{x:2}],
description: {
text: 'This is Pie chart description',
textSize: 14,
textColor: processColor('darkgray'),
}
};
I want to update values array of state by using following code but
it didn't work
const myvalues=this.state.data.dataSets[0].values.map(l => Object.assign({}, l));
myvalues[1].label = 'NEw sandwich';
this.setState({values: myvalues}, () => {
console.log(this.state.data.dataSets[0].values[1].label + " it worksss");
});
I am stuck in this
Check this
const myvalues = [] /*your new array*/
this.setState((state) =>
{
data: {
...state.data,
values: myvalues
}
});

Echarts how to highlight area between 2 line charts

I want to develop an echart that has the area between 2 linecharts highlighted in a color. To achieve this, I made use of stacked area chart. I set the color of the upper area as the highlight color and color of lower area as white so as to achieve my result. However, the color of bigger area is merging with the lower area and producing a diff color. How can I set the colors of 2 areas to not interfere? Is there a way to give z-index to the areas for this?
Here is my code:
option = {
title: {
text: '堆叠区域图'
},
tooltip : {
trigger: 'axis',
axisPointer: {
type: 'cross',
}
},
legend: {
data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎']
},
toolbox: {
feature: {
saveAsImage: {}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis : [
{
type : 'category',
boundaryGap : false,
data : ['周一','周二','周三','周四','周五','周六','周日']
}
],
yAxis : [
{
type : 'value'
}
],
series : [
{
name:'联盟广告',
type:'line',
smooth: true,
areaStyle: {color: 'red'},
data:[170, 182, 161, 184, 160, 180, 165]
},
{
name:'邮件营销',
type:'line',
smooth: true,
areaStyle: {color: 'white'},
data:[120, 132, 111, 134, 110, 130, 115]
}
]
};
What I have achieved:
You need to increase the opacity of the below chart:
option = {
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
z: -1, // optional, makes the yAxis' splitLines appear on top
data: [170, 182, 161, 184, 160, 180, 165],
smooth: true,
type: 'line',
areaStyle: {}
},
{
z: -1, // optional, makes the yAxis' splitLines appear on top
data: [120, 132, 111, 134, 110, 130, 115],
smooth: true,
type: 'line',
areaStyle: {
color: 'rgb(243, 243, 243)', // color of the background
opacity: 1, // <--- solution
},
}
]
};
The above answer only works if the series do not cross the X axis. Here is the configuration that works if your data is both above and below 0 for both upper and lower boundaries:
data = [{
"date": "2012-08-28",
"l": -2.6017329022,
"u": 0.2949717757
},
{
"date": "2012-08-29",
"l": 0.1166963635,
"u": 0.4324086347
},
{
"date": "2012-08-30",
"l": -0.8712221305,
"u": 0.0956413566
},
{
"date": "2012-08-31",
"l": -0.6541832008,
"u": 0.0717120241
},
{
"date": "2012-09-01",
"l": -1.5222677907,
"u": -0.2594188803
},
{
"date": "2012-09-02",
"l": -1.4434280535,
"u": 0.0419213465
},
{
"date": "2012-09-03",
"l": -0.3543957712,
"u": 0.0623761171
}];
myChart.setOption(option = {
xAxis: {
type: 'category',
data: data.map(function (item) {
return item.date;
})
},
yAxis: {
},
series: [
{
z: -1,
name: 'U',
type: 'line',
data: data.map(function (item) {
return item.u;
}),
lineStyle: {
opacity: 0
},
areaStyle: {
color: '#ccc',
origin: "start"
},
symbol: 'none'
},
{
name: 'L',
type: 'line',
data: data.map(function (item) {
return item.l;
}),
lineStyle: {
opacity: 0
},
z: -1,
areaStyle: {
color: "white",
origin: "start",
// opacity: 1
},
symbol: 'none'
}]
});
Create a third series with the difference between the minimum and maximum values. This data series is used only to be able to color the area between minimum and maximum values.
The stackStrategy option works from version v5.3.3
let max = [10, 22, 28, 20, 23];
let min = [8, 15, 23, 18, 19];
let dif = max.map((v, i) => min[i] - v); // [-2, -7, -5, -2, -4]
option = {
xAxis: {
data: ['A', 'B', 'C', 'D', 'E']
},
yAxis: {},
tooltip: {
trigger: 'axis',
},
series: [
{
data: max,
type: 'line',
stack: 'x', // stack name
},
{
data: dif,
type: 'line',
stack: 'x', // stack name
stackStrategy: 'positive', // strategy
lineStyle: {
opacity: 0 // hide line
},
symbol: 'none', // hide symbol
areaStyle: {
color: '#ccc'
},
tooltip: {
show: false // hide value on tooltip
}
},
{
data: min,
type: 'line',
},
]
};

How to add a hyperlink using Google Sheets API?

I'm trying to write a python script to add hyperlinks to a google sheet. I'm using the google api for this. From searching, I've gathered that I need pass the rest api a "=HYPERLINK()" type of message.
From documentation: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/other#ExtendedValue.FIELDS.formula_value
{
// Union field value can be only one of the following:
"numberValue": number,
"stringValue": string,
"boolValue": boolean,
"formulaValue": string,
"errorValue": {
object(ErrorValue)
}
// End of list of possible types for union field value.
}
It looks like I should be using the 'formulaValue' property.
Edit:
I've attempted to use the UpdateCells request
Edit: Solution below.
I figured it out:
def addHyperlink(self, hyperlink, text, sheetId, rowIndex, colIndex):
requests = []
requests.append({
"updateCells": {
"rows": [
{
"values": [{
"userEnteredValue": {
"formulaValue":"=HYPERLINK({},{})".format(hyperlink, text)
}
}]
}
],
"fields": "userEnteredValue",
"start": {
"sheetId": sheetId,
"rowIndex": rowIndex,
"columnIndex": colIndex
}
}})
body = {
"requests": requests
}
request = self.service.spreadsheets().batchUpdate(spreadsheetId=self.spreadsheetId, body=body)
return request.execute()
links not worked!!! But add like note)
def addHyperlink(self, uri_1, summa_, sheetId, rowIndex, colIndex):
requests = []
requests.append({
"updateCells": {
"rows": [{
"values": [{
'userEnteredValue': {'numberValue': float(summa_)}, #
'effectiveValue': {'numberValue': float(summa_)},
'formattedValue': "р."+summa_,
'userEnteredFormat': {
'numberFormat': {'type': 'NUMBER', 'pattern': '[$р.-419]#,##0.00'},
'backgroundColor': {'red': 1, 'green': 1, 'blue': 0.6}, 'borders': {
'top': {
'style': 'SOLID', 'width': 1, 'color': {}, 'colorStyle': {'rgbColor': {}}},
'bottom': {
'style': 'SOLID', 'width': 1, 'color': {}, 'colorStyle': {'rgbColor': {}}},
'left': {
'style': 'SOLID', 'width': 1, 'color': {}, 'colorStyle': {'rgbColor': {}}},
'right': {
'style': 'SOLID', 'width': 1, 'color': {}, 'colorStyle': {'rgbColor': {}}}},
'horizontalAlignment': 'RIGHT', 'verticalAlignment': 'BOTTOM',
'textFormat': {
'foregroundColor': {'red': 0.06666667, 'green': 0.33333334, 'blue': 0.8},
'fontFamily': 'Arial', 'underline': True,
'foregroundColorStyle': {'rgbColor': {'red': 0.06666667, 'green': 0.33333334, 'blue': 0.8}},
'link': {'uri': uri_1}
},
'hyperlinkDisplayType': 'LINKED','backgroundColorStyle': {'rgbColor': {'red': 1, 'green': 1, 'blue': 0.6}}
}
, 'hyperlink': uri_1 , 'note': uri_1,
}
]
}], "fields": '*', "start": {
"sheetId": sheetId, "rowIndex": rowIndex, "columnIndex": colIndex}}})
body = {
"requests": requests}
request = self.service.spreadsheets().batchUpdate(spreadsheetId=self.spreadsheetId, body=body)
return request.execute()

why eles.breadthFirstSearch() is behaving like dfs?

I used the following script for using the bfs function.
$(loadCy = function(){
options = {
showOverlay: false,
minZoom: 0.5,
maxZoom: 2,
style: cytoscape.stylesheet()
.selector('node')
.css({
'content': 'data(name)',
'font-family': 'helvetica',
'font-size': 24,
'text-outline-width': 3,
'text-outline-color': '#888',
'text-valign': 'center',
'color': '#fff',
'width': 'mapData(weight, 30, 80, 20, 50)',
'height': 'mapData(height, 0, 200, 10, 45)',
'border-color': '#fff'
})
.selector(':selected')
.css({
'background-color': '#000',
'line-color': '#000',
'target-arrow-color': '#000',
'text-outline-color': '#000'
})
.selector('edge')
.css({
'width': 2,
'target-arrow-shape': 'triangle'
})
,
elements: {
nodes: [
{
data: { id: 'j', name: 'Jerry', weight: 65, height: 174 }
},
{
data: { id: 'e', name: 'Elaine', weight: 48, height: 160 }
},
{
data: { id: 'k', name: 'Kramer', weight: 75, height: 185 }
},
{
data: { id: 'g', name: 'George', weight: 70, height: 150 }
}
,
{
data: { id: 'h', name: 'Hag', weight: 70, height: 150 }
}
,
{
data: { id: 'i', name: 'Iam', weight: 70, height: 150 }
}
],
edges: [
{ data: { source: 'j', target: 'e' } },
{ data: { source: 'j', target: 'k' } },
{ data: { source: 'e', target: 'j' } },
{ data: { source: 'e', target: 'k' } },
{ data: { source: 'e', target: 'g' } },
{ data: { source: 'k', target: 'j' } },
{ data: { source: 'k', target: 'e' } },
{ data: { source: 'k', target: 'g' } },
{ data: { source: 'h', target: 'g' } },
{ data: { source: 'j', target: 'h' } },
{ data: { source: 'g', target: 'i' } }
],
},
ready: function(){
cy = this;
cy.$('#j').bfs(function(i, depth){
console.log('visits ' + this.id()+depth);
}, false);
}
};
$('#cy').cytoscape(options);
});
Output on console
visits j0
visits h1
visits g2
visits i3
visits k1
visits e1
But expected output should be something like
visits j0
visits h1
visits k1
visits e1
visits g2
visits i3
Am i missing something ?
You've found a bug. That particular one has been fixed in the 2.2 branch for the soon upcoming 2.2 release. That branch also has better unit tests (incl. for bfs). You can wait until 2.2 is released, or you can gulp build on the branch to get a snapshot build now.