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

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

最佳答案

你的代码肯定有很多多余的检查。不要为长度 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为空,则比较仍然首选 measuring_point: '-' 而不是没有测量​​的标记测量点。

关于javascript - 这是将多级深层对象数组转换为简洁对象数组的好方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54409478/

相关文章:

javascript - 需要在 React Native 中将对象转换为 FlatList 的数组

java - 在 Java 中,对象数组是如何被垃圾回收的?

javascript - 使用 HTML5 嵌入 PDF 和可搜索文本?或者需要插件?

javascript - 我想将数据库元素数组提取到表中

javascript - 与特定类(class)的大多数 child 一起获取元素

arrays - 如何从同一数组的图像中提取二维数组?

c++ - new[] 是否在 C++ 中调用默认构造函数?

swift - iOS 和 Swift : ViewController class is defined, 但它是什么时候创建为对象的?

javascript - 在LiveCycle中,对象名称以#开头是什么意思?

javascript - Html5 Canvas 图形在悬停时填充