这是将多层次的深层对象转换为简洁的对象数组的好方法吗?

时间:2019-01-28 20:05:30

标签: javascript arrays object

我有大量的对象,其中每个对象都有一个键,该键包含一个对象数组(从那里到另一个层次),这些键是从Firestore数据库中检索到的。看起来像这样: 有多个人造丝(或区域),每个人造丝是一个对象。每个人造丝可以不具有一个,一个或多个测量点(对象阵列)。每个测量点可以不进行一次,一次或多次测量。每个度量都有创建日期的UNIX日期。对于每个人造丝,我需要获取最新日期的测量值,并且需要知道在哪个测量点。

在此图像中,您可以看到它已正常运行。 enter image description here 如果人造丝没有测量点,则显示破折号。

用于对其进行转换的代码如下(带有对象数组和结果)。

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并不陌生,但是我总是很想知道解决此类问题的更好方法。

1 个答案:

答案 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}}在标记的测量点上,没有测量值。