go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/common/i64.go (about)

     1  // Copyright 2020 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package common
    16  
    17  import "sort"
    18  
    19  // UniqueSorted sorts & removes duplicates in place.
    20  //
    21  // Returns the potentially shorter slice.
    22  func UniqueSorted(v []int64) []int64 {
    23  	if len(v) <= 1 {
    24  		return v
    25  	}
    26  
    27  	sort.Slice(v, func(i, j int) bool { return v[i] < v[j] })
    28  	n, prev, skipped := 0, v[0], false
    29  	for _, id := range v[1:] {
    30  		if id == prev {
    31  			skipped = true
    32  			continue
    33  		}
    34  		n++
    35  		if skipped {
    36  			v[n] = id
    37  		}
    38  		prev = id
    39  	}
    40  	return v[:n+1]
    41  }
    42  
    43  // DifferenceSorted returns all int64s in the first slice and not the second.
    44  //
    45  // Both slices must be sorted. Doesn't modify input slices.
    46  func DifferenceSorted(a, b []int64) []int64 {
    47  	var diff []int64
    48  	for {
    49  		if len(b) == 0 {
    50  			return append(diff, a...)
    51  		}
    52  		if len(a) == 0 {
    53  			return diff
    54  		}
    55  		x, y := a[0], b[0]
    56  		switch {
    57  		case x == y:
    58  			a, b = a[1:], b[1:]
    59  		case x < y:
    60  			diff = append(diff, x)
    61  			a = a[1:]
    62  		default:
    63  			b = b[1:]
    64  		}
    65  	}
    66  }
    67  
    68  // UnionSorted returns sorted unique int64s from two slices.
    69  //
    70  // Both slices must be sorted and unique. Doesn't modify input slices.
    71  func UnionSorted(a, b []int64) []int64 {
    72  	u := make([]int64, 0, len(a)+len(b))
    73  	for {
    74  		if len(b) == 0 {
    75  			return append(u, a...)
    76  		}
    77  		if len(a) == 0 {
    78  			return append(u, b...)
    79  		}
    80  		x, y := a[0], b[0]
    81  		switch {
    82  		case x == y:
    83  			a, b = a[1:], b[1:]
    84  			u = append(u, x)
    85  		case x < y:
    86  			u = append(u, x)
    87  			a = a[1:]
    88  		default:
    89  			u = append(u, y)
    90  			b = b[1:]
    91  		}
    92  	}
    93  }