3 * Copyright (c) 2004-present, Facebook, Inc.
6 * This source code is licensed under the MIT license found in the
7 * LICENSE file in the hphp/hsl/ subdirectory of this source tree.
11 namespace HH\Lib\Keyset
;
13 use namespace HH\Lib\C
;
16 * Returns a new keyset containing only the elements of the first Traversable
17 * that do not appear in any of the other ones.
19 * Time complexity: O(n + m), where n is size of `$first` and m is the combined
20 * size of `$second` plus all the `...$rest`
21 * Space complexity: O(n), where n is size of `$first`
23 function diff
<Tv1
as arraykey
, Tv2
as arraykey
>(
24 Traversable
<Tv1
> $first,
25 Traversable
<Tv2
> $second,
26 Container
<Tv2
> ...$rest
28 if (!$first is keyset
<_
>) {
29 $first = keyset($first);
31 if (C\
is_empty($first)) { // nothing to remove, so return early.
34 foreach ($second as $value) {
35 if (C\
contains_key($first, $value)) {
36 unset($first[HH\FIXME\UNSAFE_CAST
<Tv2
, Tv1
>(
38 '$value is type Tv1 because it\'s in $first',
42 foreach ($rest as $container) {
43 if (C\
is_empty($first)) { // nothing to remove, so return early.
46 foreach ($container as $value) {
47 if (C\
contains_key($first, $value)) {
48 unset($first[HH\FIXME\UNSAFE_CAST
<Tv2
, Tv1
>(
50 '$value is type Tv1 because it\'s in $first',
58 * Returns a new keyset containing all except the first `$n` elements of
59 * the given Traversable.
61 * To take only the first `$n` elements, see `Keyset\take()`.
63 * Time complexity: O(n), where n is the size of `$traversable`
64 * Space complexity: O(n), where n is the size of `$traversable`
66 function drop
<Tv
as arraykey
>(
67 Traversable
<Tv
> $traversable,
70 invariant($n >= 0, 'Expected non-negative N, got %d.', $n);
73 foreach ($traversable as $value) {
84 * Returns a new keyset containing only the values for which the given predicate
85 * returns `true`. The default predicate is casting the value to boolean.
87 * To remove null values in a typechecker-visible way, see `Keyset\filter_nulls()`.
89 * Time complexity: O(n * p), where p is the complexity of `$value_predicate`
90 * Space complexity: O(n)
92 function filter
<Tv
as arraykey
>(
93 Traversable
<Tv
> $traversable,
94 ?
(function(Tv
)[_
]: bool) $value_predicate = null,
95 )[ctx
$value_predicate]: keyset
<Tv
> {
96 $value_predicate ??
= \HH\Lib\_Private\boolval
<>;
98 foreach ($traversable as $value) {
99 if ($value_predicate($value)) {
107 * Returns a new keyset containing only non-null values of the given
110 * Time complexity: O(n)
111 * Space complexity: O(n)
113 function filter_nulls
<Tv
as arraykey
>(
114 Traversable
<?Tv
> $traversable,
117 foreach ($traversable as $value) {
118 if ($value !== null) {
126 * Returns a new keyset containing only the values for which the given predicate
129 * If you don't need access to the key, see `Keyset\filter()`.
131 * Time complexity: O(n * p), where p is the complexity of `$predicate`
132 * Space complexity: O(n)
134 function filter_with_key
<Tk
, Tv
as arraykey
>(
135 KeyedTraversable
<Tk
, Tv
> $traversable,
136 (function(Tk
, Tv
)[_
]: bool) $predicate,
137 )[ctx
$predicate]: keyset
<Tv
> {
139 foreach ($traversable as $key => $value) {
140 if ($predicate($key, $value)) {
148 * Returns a new keyset containing the keys of the given KeyedTraversable,
149 * maintaining the iteration order.
151 function keys
<Tk
as arraykey
, Tv
>(
152 KeyedTraversable
<Tk
, Tv
> $traversable,
155 foreach ($traversable as $key => $_) {
162 * Returns a new keyset containing only the elements of the first Traversable
163 * that appear in all the other ones.
165 * Time complexity: O(n + m), where n is size of `$first` and m is the combined
166 * size of `$second` plus all the `...$rest`
167 * Space complexity: O(n), where n is size of `$first`
169 function intersect
<Tv
as arraykey
>(
170 Traversable
<Tv
> $first,
171 Traversable
<Tv
> $second,
172 Container
<Tv
> ...$rest
174 if (!$first ||
!$second) {
177 $intersection = keyset($first);
179 foreach ($rest as $traversable) {
180 $next_intersection = keyset
[];
181 $keyed_traversable = keyset($traversable);
182 foreach ($intersection as $value) {
183 if (C\
contains_key($keyed_traversable, $value)) {
184 $next_intersection[] = $value;
187 if (!$next_intersection) {
190 $intersection = $next_intersection;
192 return $intersection;
196 * Returns a new keyset containing the first `$n` elements of the given
199 * If there are duplicate values in the Traversable, the keyset may be shorter
200 * than the specified length.
202 * To drop the first `$n` elements, see `Keyset\drop()`.
204 * Time complexity: O(n), where n is `$n`
205 * Space complexity: O(n), where n is `$n`
207 function take
<Tv
as arraykey
>(
208 Traversable
<Tv
> $traversable,
214 invariant($n > 0, 'Expected non-negative N, got %d.', $n);
217 foreach ($traversable as $value) {