【问题标题】:Group an array of objects by intervals按间隔对对象数组进行分组
【发布时间】:2019-01-30 13:36:21
【问题描述】:

我正在尝试通过包含在 2 个数字范围内的对象的两个属性对我的 JavaScript 对象数组进行分组(在这种情况下,在 start 和 start+2 之间)这意味着每 2 秒然后将内容连接到一个数组。

var myArray = [
{
    start: 1.1,
    end: 1.6,
    content: "you"
},
{
    start: 1.8,
    end: 2.1,
    content: "should"
},
{
    start: 2.2,
    end: 2.5,
    content: "not"
},
{
    start: 2.9,
    end: 3.1,
    content: "be"
},
{
    start: 3.6,
    end: 4.0,
    content: "here"
},
{
    start: 4.5,
    end: 5.0,
    content: "please"
},
{
    start: 5.2,
    end: 5.8,
    content: "go"
},
{
    start: 5.9,
    end: 6.3,
    content: "away"
}
];

这个想法是尝试得到这个,注意最大间隔在 2 秒之间。

var final = [
    {
        startArray: [1.1, 1.8, 2.2, 2.9],
        endArray: [1.6, 2.1, 2.5, 3.1],
        start: 1.1,
        end: 3.1,
        content: ["you", "should", "not", "be"]
    },
    {
        startArray: [3.6, 4.5],
        endArray: [4.0, 5.0],
        start: 3.6,
        end: 5.0,
        content: ["here","please"]
    },
    {
        startArray: [5.2, 5.9],
        endArray: [5.8, 6.3],
        start: 5.2,
        end: 6.3,
        content: ["go","away"]
    }
];    

我应该如何解决这个问题?帮助 :( !.

【问题讨论】:

标签: javascript arrays algorithm javascript-objects


【解决方案1】:

您可以使用 Array.prototype.reduce 迭代现有数组并构建新数组。像这样的:

let final = myArray.reduce((acc, item) => {
  let oldItem = acc.find(accItem => {
    // check if accItem is within two seconds of item
  });
  if (oldItem) {
    oldItem.startArray.push(item.start);
    // ... rest of the properties
  }
  else {
    return acc.concat({
      startArray: [item.start],
      endArray: [item.end],
      start: item.start,
      end: item.end,
      content: [item.content]
    });
  }
}, []);

【讨论】:

    【解决方案2】:

    基本代码如下,没有高级的东西:

    var final = [];
    var j = 0;
    for (var i = 0; i < myArray.length;) {
      var startArray = [];
      var endArray = [];
      var content = [];
      var start = myArray[j].start;
      var end = myArray[j].end;
      while ( i < myArray.length && (myArray[i].end - myArray[j].start) <= 2) {
        startArray[startArray.length] = myArray[i].start;
        endArray[endArray.length] = myArray[i].end;
        content[content.length] = myArray[i].content;
        end = myArray[i].end;
    
        i++;
      }
      final[final.length] = {
        startArray : startArray,
        endArray : endArray,
        start : start,
        end : end,
        content : content
      };
    
      j = i;
    }
    console.log(final);
    

    【讨论】:

      【解决方案3】:

      使用 Array.reduce 是要走的路:

      var myArray = [
      {
          start: 1.1,
          end: 1.6,
          content: "you"
      },
      {
          start: 1.8,
          end: 2.1,
          content: "should"
      },
      {
          start: 2.2,
          end: 2.5,
          content: "not"
      },
      {
          start: 2.9,
          end: 3.1,
          content: "be"
      },
      {
          start: 3.6,
          end: 4.0,
          content: "here"
      },
      {
          start: 4.5,
          end: 5.0,
          content: "please"
      },
      {
          start: 5.2,
          end: 5.8,
          content: "go"
      },
      {
          start: 5.9,
          end: 6.3,
          content: "away"
      }
      ];
      var final = [];
      function groupValues(t, v, i, a) {
          print("item " + i);
          if (t.hasOwnProperty('start') && v.end <= t.start + 2) { 
              t.startArray.push(v.start); 
              t.endArray.push(v.end); 
              t.end = v.end; 
              t.content.push(v.content);
          }
          else {
              if (t.hasOwnProperty('start')) final.push(t);
              t = { startArray: [v.start],
                   endArray: [v.end],
                   start: v.start,
                   end: v.end,
                   content: [v.content]
                  };
          }
          if (i == a.length - 1) final.push(t);
          return t;
      }
      myArray.reduce(groupValues, {});
      console.log(final);
      

      输出:

      (3) […]   ​
      0: {…}    ​​
      content: Array(4) [ "you", "should", "not", "be" ]
      end: 3.1    ​​
      endArray: Array(4) [ 1.6, 2.1, 2.5, 3.1 ]    ​​
      start: 1.1    ​​
      startArray: Array(4) [ 1.1, 1.8, 2.2, 2.9 ]
      ​​
      1: {…}    ​​
      content: Array [ "here", "please" ]    ​​
      end: 5    ​​
      endArray: Array [ 4, 5 ]    ​​
      start: 3.6    ​​
      startArray: Array [ 3.6, 4.5 ]
      ​
      2: {…}    ​​
      content: Array [ "go", "away" ]    ​​
      end: 6.3    ​​
      endArray: Array [ 5.8, 6.3 ]    ​​
      start: 5.2    ​​
      startArray: Array [ 5.2, 5.9 ]
      

      【讨论】:

        【解决方案4】:

        如果你先对数组进行排序,你只需要遍历数组并分组 neibhouring 元素:

         function groupConsecutive(array, delay = 2) {
            array.sort((a, b) => a.start - b.start);
        
           let prev = { end: -Infinity }, current;
           const result = [];
        
           for(const {start, end, content } of array) {
             if(prev.end + delay >= start) {
               // Group
               current.content.push(content);
               current.startArray.push(start);
               current.endArray.push(end);
               current.start = Math.min(current.start, start);
               current.end = Math.max(current.end, end);
             } else {
               result.push(current = {
                 startArray: [start],
                 endArray: [end],
                 content: [content],
                 start,
                 end,
              });
             }
           }
        
           return result;
         }
        

        【讨论】:

          【解决方案5】:

          假设数组已排序,可以使用Array.reduce

          let myArray=[{start:1.1,end:1.6,content:"you"},{start:1.8,end:2.1,content:"should"},{start:2.2,end:2.5,content:"not"},{start:2.9,end:3.1,content:"be"},{start:3.6,end:4.0,content:"here"},{start:4.5,end:5.0,content:"please"},{start:5.2,end:5.8,content:"go"},{start:5.9,end:6.3,content:"away"}];
          let obj;
          
          let final = myArray.reduce((a, {start, end, content}, i) => {
            /* In case of first element and an exact difference of 2.0 for 
             * previous group, obj will be undefined, hence, initializing it. */
            if (!obj) {
              obj = {start, end, startArray: [start], endArray: [end], content: [content]};
            } else {
              let diff = end - obj.start; // calculate the difference
              // If the difference is less than or equal to 2, add object to group
              if (diff <= 2) {
                obj.startArray.push(start);
                obj.endArray.push(end);
                obj.content.push(content);
                obj.end = end;
                // If the difference is exact 2, add object to final array and reset
                if (diff == 2) {
                  a.push(obj);
                  obj = undefined;
                }
              } else {
                /* For difference more than 2, add current object to array 
                 * and reset object will current value */
                a.push(obj);
                obj = {start, end, startArray: [start], endArray: [end], content: [content]};
              }
              /* At the end of iteration, if there is an object left, 
               * push it to final array */
              if(obj && i == myArray.length - 1) a.push(obj);
            }
            return a;
          }, []);
          console.log(final);

          【讨论】:

            猜你喜欢
            • 2021-04-29
            • 2021-07-07
            • 1970-01-01
            • 2016-06-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-05-05
            • 2018-05-01
            相关资源
            最近更新 更多