将项目列表转换为基于对象 属性 的范围

convert list of items to ranges based on object property

我已经为此苦苦挣扎了太久。 您将如何处理 JavaScript 中的以下内容。 源数据包含指示日期和特定长度的对象。 此列表需要转换为类似范围的对象,指示特定长度在哪一天开始和结束。

如果缺少一天,这应该是另一个范围。因此,如果我在示例中删除第 33 天,它将以 1 个额外范围对象结束(一个从 31 到 32,另一个从 34 到 35)

    const data = [
      { day: 31, length: 10 },
      { day: 32, length: 10 },
      { day: 33, length: 10 },
      { day: 34, length: 10 },
      { day: 35, length: 10 },
      
      { day: 68, length: 15 },
      { day: 69, length: 15 },
      { day: 70, length: 15 },
      { day: 71, length: 15 },
      
      { day: 80, length: 10 },
      { day: 81, length: 10 },
      
      { day: 98, length: 12 },
      { day: 99, length: 12 },
      { day: 100, length: 30 },
    ];


    const convertToWindows = (data) => {
      return ...;
    };

    const windows = [
      {
        start: 31,
        end: 35,
        length: 10,
      },
      {
        start: 68,
        end: 71,
        length: 15,
      },
      {
        start: 80,
        end: 81,
        length: 10,
      },
      {
        start: 98,
        end: 99,
        length: 12,
      },
      {
        start: 100,
        end: 100,
        length: 30,
      },
    ];

尝试这样的事情:

const data = [
      { day: 31, length: 10 },
      { day: 32, length: 10 },
      { day: 33, length: 10 },
      { day: 34, length: 10 },
      { day: 35, length: 10 },
      
      { day: 68, length: 15 },
      { day: 69, length: 15 },
      { day: 70, length: 15 },
      { day: 71, length: 15 },
      
      { day: 80, length: 10 },
      { day: 81, length: 10 },
      
      { day: 98, length: 12 },
      { day: 99, length: 12 },
      { day: 100, length: 30 },
    ];

    const convertToWindows = (data) => {
      let result = [];
      data.forEach(v => {
        let rl = result.length;
        if (rl === 0 || result[rl-1].end + 1 !== v.day || result[rl-1].length !== v.length) {
          result.push({start: v.day, end: v.day, length: v.length});
        } else result[rl-1].end += 1;
      });
      return result;
    };

    console.log(convertToWindows(data));

您可以使用一个简单的 for 循环来解决您的问题。

const data = [
  { day: 31, length: 10 },
  { day: 32, length: 10 },
  { day: 33, length: 10 },
  { day: 34, length: 10 },
  { day: 35, length: 10 },

  { day: 68, length: 15 },
  { day: 69, length: 15 },
  { day: 70, length: 15 },
  { day: 71, length: 15 },

  { day: 80, length: 10 },
  { day: 81, length: 10 },

  { day: 98, length: 12 },
  { day: 99, length: 12 },
  { day: 100, length: 30 },
];
const convertToWindows = (arr) => {
  const ret = [];
  let start = arr[0].day;
  let end = arr[0].day;
  let len = arr[0].length;
  for (let i = 1; i < arr.length; i += 1) {
    if (
      arr[i].day - arr[i - 1].day === 1 &&
      arr[i].length === arr[i - 1].length
    ) {
      end = arr[i].day;
      len = arr[i].length;
    } else {
      ret.push({
        start,
        end,
        length: len,
      });
      start = arr[i].day;
      end = arr[i].day;
      len = arr[i].length;
    }
  }
  ret.push({
    start,
    end,
    length: len,
  });
  return ret;
};

console.log(convertToWindows(data));

这样:
Optional chaining ?.
的帮助下 在 Array.reduceRight() 方法中

const data = 
  [ { day:  31, length: 10 }, { day:  32, length: 10 }, { day:  33, length: 10 }, { day:  34, length: 10 }, { day:  35, length: 10 } 
  , { day:  68, length: 15 }, { day:  69, length: 15 }, { day:  70, length: 15 }, { day:  71, length: 15 } 
  , { day:  80, length: 10 }, { day:  81, length: 10 } 
  , { day:  98, length: 12 }, { day:  99, length: 12 } 
  , { day: 100, length: 30 } 
  ]

const convertToWindows = arr => 
  arr.reduceRight((acc,{day, length}) =>
    {
    if (acc[0]?.start===(day+1) 
     && acc[0]?.length===length)
      {
      acc[0].start = day
      }
    else
      {
      acc.unshift({start:day, end:day, length})
      }
    return acc
    }
  ,[])
  ;
console.log( convertToWindows(data) )
.as-console-wrapper { max-height: 100% !important; top: 0; }