【问题标题】:Merge 2 arrays and their properties based on timestamp根据时间戳合并 2 个数组及其属性
【发布时间】:2021-10-02 14:49:41
【问题描述】:

目前我有一个包含TableRowReading数组的数组,比如let allTableReadings: TableRowReading[][]:

interface TableRowReading {
  time: number; // We can think of the timestamp `time` as the key for the object. 
  sensorValues: SensorValues[];
}

interface SensorValues {
  sensorIndex: number;
  value: number;
}

作为一个示例值,假设我们有:

let allTableReadings: TableRowReading[][] = [
// Array #1
[{  
   time: 1627315260000,
   sensorValues: [{
      sensorIndex: 0, 
      value: 5
   }]
},
{  
   time: 1627314960000,
   sensorValues: [{
      sensorIndex: 0, 
      value: 6
   }]
}],
// Array #2
[{  
   time: 1627315260000,
   sensorValues: [{
      sensorIndex: 1, 
      value: 7
   }]
}],
// Array #3
[{  
   time: 1627315260000,
   sensorValues: [{
      sensorIndex: 2, 
      value: 8
   }]
}]
]

有什么方法可以合并allTableReadings中包含的所有数组,以time为key,同时也合并sensorValues的内容?

let mergedTableReadings: TableRowReading[] = [
{  
   time: 1627315260000,
   sensorValues: [{
      sensorIndex: 0, 
      value: 5
   }, {
      sensorIndex: 1, 
      value: 7
   }, {
      sensorIndex: 2, 
      value: 8
   }]
},
{  
   time: 1627314960000,
   sensorValues: [{
      sensorIndex: 0, 
      value: 6
   }]
}
]

我被困了一段时间,但我认为我无法生成有用的代码示例。我尝试过使用扩展运算符合并并尝试找到一些方便的 lodash 函数,但没有成功。

大致思路如下:

let merged: TableRowReading[] = [];
for (let i = 0; i < allTableReadings.length; i++) {
  // merge allTableReadings[i] into merged
}

【问题讨论】:

标签: javascript arrays reactjs ecmascript-6 lodash


【解决方案1】:

使用_.flow() 创建一个函数,该函数将数组的数组展平,按time 分组,然后将每个组映射到所需的形式:

const { flow, flatten, groupBy, map, get, flatMap } = _;

const fn = flow(
  flatten,
  arr => groupBy(arr, 'time'),
  obj => map(obj, group => ({
    time: get(group, '[0].time'),
    sensorValues: flatMap(group, 'sensorValues')
  }))
);

const allTableReadings = [[{ time: 1627315260000, sensorValues: [{ sensorIndex: 0, value: 5 }] }, { time: 1627314960000, sensorValues: [{ sensorIndex: 0, value: 6 }] }],[{ time: 1627315260000, sensorValues: [{ sensorIndex: 1, value: 7 }] }],[{ time: 1627315260000, sensorValues: [{ sensorIndex: 2, value: 8 }] }] ];
   
const result = fn(allTableReadings);

console.log(result);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"&gt;&lt;/script&gt;

您可以使用 lodash/fp 获得相同想法的简洁版本:

const { flow, flatten, groupBy, map, get, flatMap } = _;

const fn = flow(
  flatten,
  groupBy('time'),
  map(group => ({
    time: get('[0].time', group),
    sensorValues: flatMap('sensorValues', group)
  }))
);

const allTableReadings = [[{ time: 1627315260000, sensorValues: [{ sensorIndex: 0, value: 5 }] }, { time: 1627314960000, sensorValues: [{ sensorIndex: 0, value: 6 }] }],[{ time: 1627315260000, sensorValues: [{ sensorIndex: 1, value: 7 }] }],[{ time: 1627315260000, sensorValues: [{ sensorIndex: 2, value: 8 }] }] ];
   
const result = fn(allTableReadings);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.fp.min.js" integrity="sha512-PQPary7Ah0W8wFgizjGNg0jWpVUKLAxUCvdTNS4lpQFUtoeg5cmSaI8cJK3zh5TDgHDMMHo3tG3ZcLideDlRuQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

【讨论】:

    【解决方案2】:

    检查此代码。

    let arr = [{
        time: 1627315260000,
        sensorValues: [{
          sensorIndex: 0,
          value: 5
        }]
      },
      {
        time: 1627314960000,
        sensorValues: [{
          sensorIndex: 0,
          value: 6
        }]
      },
      [{
        time: 1627315260000,
        sensorValues: [{
          sensorIndex: 1,
          value: 7
        }]
      }],
      [{
        time: 1627315260000,
        sensorValues: [{
          sensorIndex: 2,
          value: 8
        }]
      }]
    ]
    
    
    arr=arr.flat();
    
    var newArray = [];
    
    for(var i = 0; i< arr.length; i++){
      var idx = newArray.findIndex(x => x.time === arr[i].time);
      if(idx < 0){
        newArray.push(arr[i]);
      } else {
        var newValues = newArray[idx].sensorValues.concat(arr[i].sensorValues);
        newArray[idx].sensorValues = newValues;
      }
    }
    
    
    console.log(newArray)

    【讨论】:

      【解决方案3】:

      你可以这样做:

      let obj = [[{ time: 1627315260000, sensorValues: [{ sensorIndex: 0, value: 5 }] }, { time: 1627314960000, sensorValues: [{ sensorIndex: 0, value: 6 }] }],[{ time: 1627315260000, sensorValues: [{ sensorIndex: 1, value: 7 }] }],[{ time: 1627315260000, sensorValues: [{ sensorIndex: 2, value: 8 }] }] ];
         
      
      let result = [];
      
      // Array where saved times would be push
      let times = []; 
      // Flat the array in order toconvert it to a 1D array
      obj.flat().forEach(e => {
        // If time isn't saved, push it in the 'times' array and in the 'result' array
        if (!times.includes(e.time)) {
          times.push(e.time);
          result.push({
            time: e.time,
            sensorValues: []
          });
        }
        // Save sensor values
        result[times.indexOf(e.time)].sensorValues.push(...e.sensorValues);
      });
      
      console.log(result);

      【讨论】:

        猜你喜欢
        • 2019-03-03
        • 1970-01-01
        • 2018-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多