我有大量的对象,其中每个对象都有一个键,该键包含一个对象数组(从那里到另一个层次),这些键是从Firestore数据库中检索到的。看起来像这样: 有多个人造丝(或区域),每个人造丝是一个对象。每个人造丝可以不具有一个,一个或多个测量点(对象阵列)。每个测量点可以不进行一次,一次或多次测量。每个度量都有创建日期的UNIX日期。对于每个人造丝,我需要获取最新日期的测量值,并且需要知道在哪个测量点。
在此图像中,您可以看到它已正常运行。
如果人造丝没有测量点,则显示破折号。
用于对其进行转换的代码如下(带有对象数组和结果)。
const rayons = [
{
"uid": "1///rayons/FaexjdCxsYECRVTghU6R",
"measuring_points": [
{
"uid": "1///rayons/FaexjdCxsYECRVTghU6R/measuring_points/LCkJoEt6oCkPYKqC3i27",
"measurements": [
{
"uid": "1///rayons/FaexjdCxsYECRVTghU6R/measuring_points/LCkJoEt6oCkPYKqC3i27/measurements/sT7ar4ezHWdGPJnNmm2C",
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"date_added": {
"seconds": 1554804000,
"nanoseconds": 0
},
"ice_thickness": 1.5,
"is_deleted": false,
"notes": "Snow was yellow for some reason",
"snow_height": 5
},
{
"uid": "1///rayons/FaexjdCxsYECRVTghU6R/measuring_points/LCkJoEt6oCkPYKqC3i27/measurements/sFglNwTUYU1mKXREyjen",
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"date_added": {
"seconds": 1544883008,
"nanoseconds": 241000000
},
"ice_thickness": 2,
"is_deleted": false,
"notes": "een opmerking",
"snow_height": 3
}
],
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"is_deleted": false,
"location": {
"_lat": 52.9416192,
"_long": 5.8114048
},
"name": "Main Point Balk"
}
],
"name": "Balk",
"users": [
"i7gvYo3W9UQynanw1xDXnOOAImk2",
"6Ijf3gKvLghET8yCEfaC1iAbi0j1",
"uyUR2xVvlvWMpV1J2OClOeUILwM2"
]
},
{
"uid": "1///rayons/oKKKMTAdtinC34Mui3R0",
"measuring_points": [
{
"uid": "1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/Hc72pD4nPZoAO8xYXIVo",
"measurements": [
{
"uid": "1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/Hc72pD4nPZoAO8xYXIVo/measurements/ufhxEaVAvTOiUAxEuah3",
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"date_added": {
"seconds": 1548621505,
"nanoseconds": 90000000
},
"ice_thickness": 0.5,
"is_deleted": false,
"notes": "",
"snow_height": 0
}
],
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"is_deleted": false,
"location": {
"_lat": 52.941685299999996,
"_long": 5.8107096
},
"name": "1.2 Test"
},
{
"uid": "1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/HfZ0Mxq7lkvq1HWp4iP9",
"measurements": [
{
"uid": "1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/HfZ0Mxq7lkvq1HWp4iP9/measurements/kGg3xcMHWjZhYwJ8sGXc",
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"date_added": {
"seconds": 1548621856,
"nanoseconds": 502000000
},
"ice_thickness": 11,
"is_deleted": false,
"notes": "",
"snow_height": 0
},
{
"uid": "1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/HfZ0Mxq7lkvq1HWp4iP9/measurements/QYCJZIfgtYh0CdzgT99f",
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"date_added": {
"seconds": 1548605585,
"nanoseconds": 992000000
},
"ice_thickness": 1.5,
"is_deleted": false,
"notes": "",
"snow_height": 0
}
],
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"is_deleted": false,
"location": {
"_lat": 52.941685299999996,
"_long": 5.8107096
},
"name": "1.1 Test"
},
{
"uid": "1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/yc64NpCFeln4sQQjeXef",
"measurements": [],
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"is_deleted": false,
"location": {
"_lat": 52.941685299999996,
"_long": 5.8107096
},
"name": "1.10 Test"
}
],
"name": "Joure",
"users": []
},
{
"uid": "1///rayons/H20FJdCAP7WR1CYUCXdQ",
"measuring_points": [
{
"uid": "1///rayons/H20FJdCAP7WR1CYUCXdQ/measuring_points/9Lwbaf9UnHDONkF78uIb",
"measurements": [
{
"uid": "1///rayons/H20FJdCAP7WR1CYUCXdQ/measuring_points/9Lwbaf9UnHDONkF78uIb/measurements/6b7kMXQISqzaHMYGhMwc",
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"date_added": {
"seconds": 1548620524,
"nanoseconds": 55000000
},
"ice_thickness": 6,
"is_deleted": false,
"notes": "",
"snow_height": 0
}
],
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"is_deleted": false,
"location": {
"_lat": 53.197598005739415,
"_long": 5.757791419036211
},
"name": "Ferbiningskanaal"
},
{
"uid": "1///rayons/H20FJdCAP7WR1CYUCXdQ/measuring_points/p2Z71ttO8UBDmUacezIU",
"measurements": [
{
"uid": "1///rayons/H20FJdCAP7WR1CYUCXdQ/measuring_points/p2Z71ttO8UBDmUacezIU/measurements/Edb6Zr7pVnS16odfmNew",
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"date_added": {
"seconds": 1541761200,
"nanoseconds": 0
},
"ice_thickness": 2,
"is_deleted": false,
"notes": "",
"snow_height": 0
}
],
"added_by": "i7gvYo3W9UQynanw1xDXnOOAImk2",
"is_deleted": false,
"location": {
"_lat": 52.370215699999996,
"_long": 4.895167900000001
},
"name": "Leeuwarden Centrum"
}
],
"name": "Leeuwarden",
"users": [
""
]
},
{
"uid": "1///rayons/ffBCDYi8xRkFOkbS4Gk7",
"measuring_points": [],
"name": "Munnekeburen",
"users": []
}
]
const result = rayons
.map(({ name: rayon, measuring_points }) => {
// Bail early.
if (!measuring_points.length)
return {
rayon,
measuring_point: '-',
date: '-',
ice_thickness: '-',
}
// Check if there's a single measuring point.
if (measuring_points.length && measuring_points.length === 1) {
// Go through all measuring points and return an array with one object.
let array = measuring_points.reduce((accumulator, { name: measuring_point, measurements }) => {
// Bail early.
if (!measurements.length) return
let newestMeasurementCleaned = {}
// Check if there's a single measurement.
if (measurements.length === 1) {
// Return the first and only measurement with the names of the rayon and measuring point.
let {
date_added: { seconds: date },
ice_thickness,
} = measurements[0]
newestMeasurementCleaned = {
rayon,
measuring_point,
date,
ice_thickness,
}
// Check if there's more than one measurement.
} else if (measurements.length > 1) {
// Return the measurement with the newest date and the names of the rayon and measuring point.
let {
date_added: { seconds: date },
ice_thickness,
} = measurements.reduce(
(prev, curr) => {
return prev.date_added.seconds > curr.date_added.seconds ? prev : curr
},
{ date_added: { seconds: 0 } }
)
newestMeasurementCleaned = {
rayon,
measuring_point,
date,
ice_thickness,
}
}
return accumulator.concat(newestMeasurementCleaned)
}, [])
return array[0]
// Check if there's more than one single measuring point.
} else if (measuring_points.length && measuring_points.length > 1) {
// Go through all measuring points, filter out undefined and return a single object.
let object = measuring_points
.map(({ name: measuring_point, measurements }) => {
// Bail early.
if (!measurements.length) return
let newestMeasurementCleaned = {}
// Check if there's a single measurement.
if (measurements.length === 1) {
// Return the first and only measurement with the names of the rayon and measuring point.
let {
date_added: { seconds: date },
ice_thickness,
} = measurements[0]
newestMeasurementCleaned = {
rayon,
measuring_point,
date,
ice_thickness,
}
// Check if there's more than one measurement.
} else if (measurements.length > 1) {
// Return the measurement with the newest date and the names of the rayon and measuring point.
let {
date_added: { seconds: date },
ice_thickness,
} = measurements.reduce(
(prev, curr) => {
return prev.date_added.seconds > curr.date_added.seconds ? prev : curr
},
{ date_added: { seconds: 0 } }
)
newestMeasurementCleaned = {
rayon,
measuring_point,
date,
ice_thickness,
}
}
return newestMeasurementCleaned
})
.filter(item => typeof item !== 'undefined')
.reduce(
(prev, curr) => {
return prev.date > curr.date ? prev : curr
},
{ date: 0 }
)
return object
}
})
.filter(item => typeof item !== 'undefined')
console.log(result)
我的问题是,这是执行此操作的好方法,还是有更好,更简单或更简洁的方法?我对Javascript并不陌生,但是我总是很想知道解决此类问题的更好方法。
答案 0 :(得分:1)
您的代码中肯定有很多多余的检查。不要写最后一个分支应该能够自行处理的长度为0和1的不必要的基本情况。与具有DRY代码的改进的可读性相比,性能的改进可以忽略不计。如果以后发现程序要减少的数据集花费的时间太长,请然后配置文件并确定要优化的实现。
const rayons = [{uid:'1///rayons/FaexjdCxsYECRVTghU6R',measuring_points:[{uid:'1///rayons/FaexjdCxsYECRVTghU6R/measuring_points/LCkJoEt6oCkPYKqC3i27',measurements:[{uid:'1///rayons/FaexjdCxsYECRVTghU6R/measuring_points/LCkJoEt6oCkPYKqC3i27/measurements/sT7ar4ezHWdGPJnNmm2C',added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',date_added:{seconds:1554804000,nanoseconds:0},ice_thickness:1.5,is_deleted:false,notes:'Snow was yellow for some reason',snow_height:5},{uid:'1///rayons/FaexjdCxsYECRVTghU6R/measuring_points/LCkJoEt6oCkPYKqC3i27/measurements/sFglNwTUYU1mKXREyjen',added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',date_added:{seconds:1544883008,nanoseconds:241000000},ice_thickness:2,is_deleted:false,notes:'een opmerking',snow_height:3}],added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',is_deleted:false,location:{_lat:52.9416192,_long:5.8114048},name:'Main Point Balk'}],name:'Balk',users:['i7gvYo3W9UQynanw1xDXnOOAImk2','6Ijf3gKvLghET8yCEfaC1iAbi0j1','uyUR2xVvlvWMpV1J2OClOeUILwM2']},{uid:'1///rayons/oKKKMTAdtinC34Mui3R0',measuring_points:[{uid:'1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/Hc72pD4nPZoAO8xYXIVo',measurements:[{uid:'1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/Hc72pD4nPZoAO8xYXIVo/measurements/ufhxEaVAvTOiUAxEuah3',added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',date_added:{seconds:1548621505,nanoseconds:90000000},ice_thickness:0.5,is_deleted:false,notes:'',snow_height:0}],added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',is_deleted:false,location:{_lat:52.941685299999996,_long:5.8107096},name:'1.2 Test'},{uid:'1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/HfZ0Mxq7lkvq1HWp4iP9',measurements:[{uid:'1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/HfZ0Mxq7lkvq1HWp4iP9/measurements/kGg3xcMHWjZhYwJ8sGXc',added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',date_added:{seconds:1548621856,nanoseconds:502000000},ice_thickness:11,is_deleted:false,notes:'',snow_height:0},{uid:'1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/HfZ0Mxq7lkvq1HWp4iP9/measurements/QYCJZIfgtYh0CdzgT99f',added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',date_added:{seconds:1548605585,nanoseconds:992000000},ice_thickness:1.5,is_deleted:false,notes:'',snow_height:0}],added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',is_deleted:false,location:{_lat:52.941685299999996,_long:5.8107096},name:'1.1 Test'},{uid:'1///rayons/oKKKMTAdtinC34Mui3R0/measuring_points/yc64NpCFeln4sQQjeXef',measurements:[],added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',is_deleted:false,location:{_lat:52.941685299999996,_long:5.8107096},name:'1.10 Test'}],name:'Joure',users:[]},{uid:'1///rayons/H20FJdCAP7WR1CYUCXdQ',measuring_points:[{uid:'1///rayons/H20FJdCAP7WR1CYUCXdQ/measuring_points/9Lwbaf9UnHDONkF78uIb',measurements:[{uid:'1///rayons/H20FJdCAP7WR1CYUCXdQ/measuring_points/9Lwbaf9UnHDONkF78uIb/measurements/6b7kMXQISqzaHMYGhMwc',added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',date_added:{seconds:1548620524,nanoseconds:55000000},ice_thickness:6,is_deleted:false,notes:'',snow_height:0}],added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',is_deleted:false,location:{_lat:53.197598005739415,_long:5.757791419036211},name:'Ferbiningskanaal'},{uid:'1///rayons/H20FJdCAP7WR1CYUCXdQ/measuring_points/p2Z71ttO8UBDmUacezIU',measurements:[{uid:'1///rayons/H20FJdCAP7WR1CYUCXdQ/measuring_points/p2Z71ttO8UBDmUacezIU/measurements/Edb6Zr7pVnS16odfmNew',added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',date_added:{seconds:1541761200,nanoseconds:0},ice_thickness:2,is_deleted:false,notes:'',snow_height:0}],added_by:'i7gvYo3W9UQynanw1xDXnOOAImk2',is_deleted:false,location:{_lat:52.370215699999996,_long:4.895167900000001},name:'Leeuwarden Centrum'}],name:'Leeuwarden',users:['']},{uid:'1///rayons/ffBCDYi8xRkFOkbS4Gk7',measuring_points:[],name:'Munnekeburen',users:[]}]
const result = rayons.map(({ name: rayon, measuring_points }) =>
measuring_points.reduce((acc, { name: measuring_point, measurements }) => {
const measurement = measurements.reduce(
(acc, { date_added: { seconds: date }, ice_thickness }) => acc.date >= date
? acc
: { rayon, measuring_point, date, ice_thickness },
{ rayon, measuring_point, date: -Infinity, ice_thickness: '-' }
)
return acc.date >= measurement.date
? acc
: measurement
}, {
rayon,
measuring_point: '-',
date: null,
ice_thickness: '-'
})
).map(rayon => {
if (rayon.date === null) rayon.date = '-'
return rayon
})
console.log(result)
对于日期比较,null
等同于使用0
,但是在完成减少测量点之后可以显式检查它是否映射到'-'
。内部累加器的初始值的日期为-Infinity
,小于日期null
或任何数值,因此,如果measurements
为空,则比较仍首选{ {1}}在标记的测量点上,没有测量值。