簡體   English   中英

是否有更優雅的解決方案來獲取范圍數組的倒數?

[英]Is there a more elegant solution to getting the inverse of an array of ranges?

讓我們想象一下:

您有一條從 1 開始到 10000 結束的行。

你得到一個范圍數組,如[{ start: 5, end: 10 }, { start: 15, end: 25 }]

給定一個范圍數組,求逆。

對於上面的例子,逆將是[{ start: 1, end: 4 }, { start: 11, end: 14 }, { start: 26, end: 10000 }]

請注意,我們線上的其他范圍基本上都是倒數。

下面是我目前的解決方案......是否有更優雅的解決方案,不必明確處理邊緣情況?

請注意,在我的代碼范圍中是命名區域。

const inverseRegions = (regions) => {

  // If no regions, the inverse is the entire line.
  if (regions.length === 0) { 
    return [{ start: 1, end: 10000 }] 
  }

  let result = []

  // If the first region doesn't start at the beginning of the line
  // we need to account for the region from the 1 to the start of
  // first region
  if (regions[0].start !== 1) {
    result.push({
      start: 1,
      end: regions[0].start - 1
    })
  }

  for (let i = 1; i < regions.length; i++) {
    const previousRegion = regions[i-1]
    const region = regions[i]

    result.push({
      start: previousRegion.end + 1,
      end: region.start - 1
    })
  }

  // If the last region doesn't end at the end of the line
  // we need to account for the region from the end of the last
  // region to 10000
  if (regions[regions.length - 1].end !== 10000) {
    result.push({
      start: regions[regions.length - 1].end + 1,
      end: 10000
    })
  }

  return result
}

預期成績:

inverseRegions([]) 
  => [ { start: 1, end: 10000 } ]

inverseRegions([{ start: 1, end: 10 }, { start: 15, end: 20 }]) 
  => [ { start: 11, end: 14 }, 
       { start: 21, end: 10000 } ]

inverseRegions([{ start: 5, end: 10 }, { start: 12, end: 60 }, { start: 66, end: 10000 }]) 
  => [ { start: 1, end: 4 },
       { start: 11, end: 11 },
       { start: 61, end: 65 } ]

inverseRegions([{ start: 8, end: 12 }, { start: 16, end: 20 }, { start: 29, end: 51 }]) 
  => [ { start: 1, end: 7 },
       { start: 13, end: 15 },
       { start: 21, end: 28 },
       { start: 52, end: 10000 } ]

您可以使用使用包含整個區域的累加器初始化的reduce ,然后在遇到新范圍時拆分最后一個區域:

 function inverseRegions(ranges) { return ranges.reduce((acc, curr) => { let prev = acc.pop(); if (curr.start > prev.start) acc.push({start: prev.start, end: curr.start - 1}) if (prev.end > curr.end) acc.push({start: curr.end + 1, end: prev.end}); return acc; }, [{start: 1, end: 10000}]) } console.log(inverseRegions([{ start: 5, end: 10 }, { start: 15, end: 25 }])); console.log(inverseRegions([])); console.log(inverseRegions([{ start: 1, end: 10 }, { start: 15, end: 20 }])); console.log(inverseRegions([{ start: 5, end: 10 }, { start: 12, end: 60 }, { start: 66, end: 10000 }])); console.log(inverseRegions([{ start: 8, end: 12 }, { start: 16, end: 20 }, { start: 29, end: 51 }]));

這當然假設您的間隔已排序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM