将连字符分隔的字符串范围合并为区间

huangapple go评论81阅读模式
英文:

Merging Intervals out of hyphenated string ranges

问题

我有一个这样的字符串:
ports := []string{"1", "2-7", "12-1200", "10-500"}

我想将其转换为整数集合,输出应该是:

[]intSet{1, 2-7, 10-1200}

其中intSet是某种整数集合,我可以轻松地添加和删除元素。

更新1

intSet是一个sets列表。
所以,2-7也是一个集合。

更新2

这里最大的集合被合并。

例如:

  • "1" -> 1
  • "2-7" -> 2-7
  • "12-1200" 和 "10-500" => "10..12.....500....1200" -> 10-1200

由于它是一个set,因此它包含了一个唯一的范围,该范围覆盖整个集合。

英文:

I have a string like this:
ports := []string{"1", "2-7", "12-1200", "10-500"}

I would like to make an integer set out of this like the output should be :

[]intSet{ 1, 2-7, 10-1200 }

Where intSet is some kind of integer set from which I am able to easily remove and add elements.

Update 1

intSet is a list of sets.
So, 2-7 is also a set.

Update 2

Here the largest set is merged.

e.g.

  • "1" -> 1
  • "2-7" -> 2-7
  • "12-1200" & "10-500" => "10..12.....500....1200" -> 10-1200

Since it's a set so it encompasses a unique range for this, a range which covers the whole set.

答案1

得分: 2

package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"
)

type intSet struct {
	start int
	end   int
}

func (s intSet) String() string {
	if s.start == s.end {
		return fmt.Sprintf("%d", s.start)
	}
	return fmt.Sprintf("%d-%d", s.start, s.end)
}

func (s intSet) in(i int) bool {
	return s.start <= i && i <= s.end
}

func (s *intSet) union(set intSet) {
	if set.start < s.start {
		s.start = set.start
	}

	if set.end > s.end {
		s.end = set.end
	}
}

func insert(set intSet, is []intSet) bool {
	for i, s := range is {
		if s.in(set.start) || s.in(set.end) {
			is[i].union(set)
			return true
		}
		//updated here with thankful to @mh-cbon
		if set.in(s.start) || set.in(s.end) {
			is[i].union(set)
			return true
		}
	}
	return false
}

func main() {
	var set []intSet
	ports := []string{"1", "2-7", "12-1200", "10-500", "9-5500"}
	for _, port := range ports {
		s := strings.Split(port, "-")
		if len(s) < 1 || len(s) > 2 {
			log.Fatalln("set不能有多个值或没有值")
		}
		start, err := strconv.Atoi(s[0])
		if err != nil {
			log.Fatalln(err)
		}
		end := start
		if len(s) == 2 {
			end, err = strconv.Atoi(s[1])
			if err != nil {
				log.Fatalln(err)
			}
		}

		temSet := intSet{
			start: start,
			end:   end,
		}
		if !insert(temSet, set) {
			set = append(set, temSet)
		}
	}

	fmt.Println(set) //[1 2-7 9-5500]
}

这里运行

英文:
package main
import (
&quot;fmt&quot;
&quot;log&quot;
&quot;strconv&quot;
&quot;strings&quot;
)
type intSet struct {
start int
end   int
}
func (s intSet) String() string {
if s.start == s.end {
return fmt.Sprintf(&quot;%d&quot;, s.start)
}
return fmt.Sprintf(&quot;%d-%d&quot;, s.start, s.end)
}
func (s intSet) in(i int) bool {
return s.start &lt;= i &amp;&amp; i &lt;= s.end
}
func (s *intSet) union(set intSet) {
if set.start &lt; s.start {
s.start = set.start
}
if set.end &gt; s.end {
s.end = set.end
}
}
func insert(set intSet, is []intSet) bool {
for i, s := range is {
if s.in(set.start) || s.in(set.end) {
is[i].union(set)
return true
}
//updated here with thankful to @mh-cbon
if set.in(s.start) || set.in(s.end) {
is[i].union(set)
return true
}
}
return false
}
func main() {
var set []intSet
ports := []string{&quot;1&quot;, &quot;2-7&quot;, &quot;12-1200&quot;, &quot;10-500&quot;, &quot;9-5500&quot;}
for _, port := range ports {
s := strings.Split(port, `-`)
if len(s) &lt; 1 || len(s) &gt; 2 {
log.Fatalln(`set cannot have multiple values or no value`)
}
start, err := strconv.Atoi(s[0])
if err != nil {
log.Fatalln(err)
}
end := start
if len(s) == 2 {
end, err = strconv.Atoi(s[1])
if err != nil {
log.Fatalln(err)
}
}
temSet := intSet{
start: start,
end:   end,
}
if !insert(temSet, set) {
set = append(set, temSet)
}
}
fmt.Println(set) //[1 2-7 9-5500]
}

run here

huangapple
  • 本文由 发表于 2021年8月6日 15:12:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/68677575.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定