1
- const SWISS_DICT_LOAD_FACTOR = 0.75
1
+ const SWISS_DICT_LOAD_FACTOR = 0.97
2
2
const _u8x16 = NTuple{16 , VecElement{UInt8}}
3
3
4
+ """
5
+ SwissDict([itr])
6
+
7
+ `SwissDict{K,V}()` constructs a hash table with keys of type `K` and values of type `V`.
8
+ Keys are compared with [`isequal`](@ref) and hashed with [`hash`](@ref).
9
+ Given a single iterable argument, constructs a [`SwissDict`](@ref) whose key-value pairs
10
+ are taken from 2-tuples `(key,value)` generated by the argument.
11
+
12
+ # Examples
13
+ ```jldoctest
14
+ julia> SwissDict([("A", 1), ("B", 2)])
15
+ SwissDict{String,Int64} with 2 entries:
16
+ "B" => 2
17
+ "A" => 1
18
+ ```
19
+
20
+ Alternatively, a sequence of pair arguments may be passed.
21
+
22
+ ```jldoctest
23
+ julia> SwissDict("A"=>1, "B"=>2)
24
+ SwissDict{String,Int64} with 2 entries:
25
+ "B" => 2
26
+ "A" => 1
27
+ ```
28
+ """
4
29
mutable struct SwissDict{K,V} <: AbstractDict{K,V}
5
30
slots:: Vector{_u8x16}
6
31
keys:: Vector{K}
@@ -57,7 +82,7 @@ function SwissDict(kv)
57
82
end
58
83
end
59
84
60
- # # SIMD utilities
85
+ # SIMD utilities
61
86
@inline _expand16 (u:: UInt8 ) = ntuple (i-> VecElement (u), Val (16 ))
62
87
_blsr (i:: UInt32 )= i & (i- Int32 (1 ))
63
88
@@ -215,6 +240,7 @@ function _iterslots(h::SwissDict, start::Int)
215
240
sl = ((~ sl & 0xffff )>> off) << off
216
241
return _iterslots (h, (i0, sl))
217
242
end
243
+
218
244
function _iterslots (h:: SwissDict , state)
219
245
i, sl = state
220
246
while iszero (sl)
@@ -248,12 +274,6 @@ function maybe_rehash_shrink!(h::SwissDict)
248
274
end
249
275
end
250
276
251
- # function _dictsizehint(sz)
252
- # (sz <= 16) && return 16
253
- # nsz = _tablesz(sz)
254
- # return (sz > SWISS_DICT_LOAD_FACTOR*nsz) ? (nsz<<1) : nsz
255
- # end
256
-
257
277
function sizehint! (d:: SwissDict , newsz)
258
278
newsz = _tablesz (newsz* 2 ) # *2 for keys and values in same array
259
279
oldsz = length (d. keys)
328
348
isempty (t:: SwissDict ) = (t. count == 0 )
329
349
length (t:: SwissDict ) = t. count
330
350
351
+ """
352
+ empty!(collection) -> collection
353
+
354
+ Remove all elements from a `collection`.
355
+
356
+ # Examples
357
+ ```jldoctest
358
+ julia> A = SwissDict("a" => 1, "b" => 2)
359
+ SwissDict{String,Int64} with 2 entries:
360
+ "b" => 2
361
+ "a" => 1
362
+
363
+ julia> empty!(A);
364
+
365
+ julia> A
366
+ SwissDict{String,Int64} with 0 entries
367
+ ```
368
+ """
331
369
function empty! (h:: SwissDict{K,V} ) where {K, V}
332
370
fill! (h. slots, _expand16 (0x00 ))
333
371
sz = length (h. keys)
344
382
345
383
function setindex! (h:: SwissDict{K,V} , v0, key0) where {K, V}
346
384
key = convert (K, key0)
347
- if ! isequal (key, key0)
348
- throw (ArgumentError (" $(limitrepr (key0)) is not a valid key for type $K " ))
349
- end
350
385
_setindex! (h, v0, key)
351
386
end
352
387
@@ -359,23 +394,61 @@ function _setindex!(h::SwissDict{K,V}, v0, key::K) where {K, V}
359
394
@inbounds h. keys[index] = key
360
395
@inbounds h. vals[index] = v
361
396
else
362
- @inbounds _setindex! (h, v, key, - index, tag)
397
+ _setindex! (h, v, key, - index, tag)
363
398
end
364
399
365
400
return h
366
401
end
367
402
403
+ """
404
+ get!(collection, key, default)
405
+
406
+ Return the value stored for the given key, or if no mapping for the key is present, store
407
+ `key => default`, and return `default`.
408
+
409
+ # Examples
410
+ ```jldoctest
411
+ julia> d = SwissDict("a"=>1, "b"=>2, "c"=>3);
412
+
413
+ julia> get!(d, "a", 5)
414
+ 1
415
+
416
+ julia> get!(d, "d", 4)
417
+ 4
418
+
419
+ julia> d
420
+ SwissDict{String,Int64} with 4 entries:
421
+ "c" => 3
422
+ "b" => 2
423
+ "a" => 1
424
+ "d" => 4
425
+ ```
426
+ """
368
427
get! (h:: SwissDict{K,V} , key0, default) where {K,V} = get! (()-> default, h, key0)
369
428
429
+ """
430
+ get!(f::Function, collection, key)
431
+
432
+ Return the value stored for the given key, or if no mapping for the key is present, store
433
+ `key => f()`, and return `f()`.
434
+
435
+ This is intended to be called using `do` block syntax:
436
+ ```julia
437
+ get!(dict, key) do
438
+ # default value calculated here
439
+ time()
440
+ end
441
+ ```
442
+ """
370
443
function get! (default:: Callable , h:: SwissDict{K,V} , key0) where {K, V}
371
444
key = convert (K, key0)
372
- return get ! (default, h, key)
445
+ return _get ! (default, h, key)
373
446
end
374
447
375
- function get ! (default:: Callable , h:: SwissDict{K,V} , key:: K ) where {K, V}
448
+ function _get ! (default:: Callable , h:: SwissDict{K,V} , key:: K ) where {K, V}
376
449
index, tag = ht_keyindex2! (h, key)
377
450
378
- index > 0 && return h. vals[index]
451
+ index > 0 && return @inbounds h. vals[index]
379
452
380
453
age0 = h. age
381
454
v = convert (V, default ())
@@ -387,7 +460,7 @@ function get!(default::Callable, h::SwissDict{K,V}, key::K) where {K, V}
387
460
@inbounds h. keys[index] = key
388
461
@inbounds h. vals[index] = v
389
462
else
390
- @inbounds _setindex! (h, v, key, - index, tag)
463
+ _setindex! (h, v, key, - index, tag)
391
464
end
392
465
return v
393
466
end
@@ -397,25 +470,118 @@ function getindex(h::SwissDict{K,V}, key) where {K, V}
397
470
@inbounds return (index < 0 ) ? throw (KeyError (key)) : h. vals[index]:: V
398
471
end
399
472
473
+ """
474
+ get(collection, key, default)
475
+
476
+ Return the value stored for the given key, or the given default value if no mapping for the
477
+ key is present.
478
+
479
+ # Examples
480
+ ```jldoctest
481
+ julia> d = SwissDict("a"=>1, "b"=>2);
482
+
483
+ julia> get(d, "a", 3)
484
+ 1
485
+
486
+ julia> get(d, "c", 3)
487
+ 3
488
+ ```
489
+ """
400
490
function get (h:: SwissDict{K,V} , key, default) where {K, V}
401
491
index = ht_keyindex (h, key)
402
492
@inbounds return (index < 0 ) ? default : h. vals[index]:: V
403
493
end
404
494
495
+ """
496
+ get(f::Function, collection, key)
497
+
498
+ Return the value stored for the given key, or if no mapping for the key is present, return
499
+ `f()`. Use [`get!`](@ref) to also store the default value in the dictionary.
500
+
501
+ This is intended to be called using `do` block syntax
502
+
503
+ ```julia
504
+ get(dict, key) do
505
+ # default value calculated here
506
+ time()
507
+ end
508
+ ```
509
+ """
405
510
function get (default:: Callable , h:: SwissDict{K,V} , key) where {K, V}
406
511
index = ht_keyindex (h, key)
407
512
@inbounds return (index < 0 ) ? default () : h. vals[index]:: V
408
513
end
409
514
515
+ """
516
+ haskey(collection, key) -> Bool
517
+
518
+ Determine whether a collection has a mapping for a given `key`.
519
+
520
+ # Examples
521
+ ```jldoctest
522
+ julia> D = SwissDict('a'=>2, 'b'=>3)
523
+ SwissDict{Char,Int64} with 2 entries:
524
+ 'a' => 2
525
+ 'b' => 3
526
+
527
+ julia> haskey(D, 'a')
528
+ true
529
+
530
+ julia> haskey(D, 'c')
531
+ false
532
+ ```
533
+ """
410
534
haskey (h:: SwissDict , key) = (ht_keyindex (h, key) > 0 )
411
535
in (key, v:: KeySet{<:Any, <:SwissDict} ) = (ht_keyindex (v. dict, key) > 0 )
412
536
537
+ """
538
+ getkey(collection, key, default)
539
+
540
+ Return the key matching argument `key` if one exists in `collection`, otherwise return `default`.
541
+
542
+ # Examples
543
+ ```jldoctest
544
+ julia> D = SwissDict('a'=>2, 'b'=>3)
545
+ SwissDict{Char,Int64} with 2 entries:
546
+ 'a' => 2
547
+ 'b' => 3
548
+
549
+ julia> getkey(D, 'a', 1)
550
+ 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
413
551
552
+ julia> getkey(D, 'd', 'a')
553
+ 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
554
+ ```
555
+ """
414
556
function getkey (h:: SwissDict{K,V} , key, default) where {K, V}
415
557
index = ht_keyindex (h, key)
416
558
@inbounds return (index< 0 ) ? default : h. keys[index]:: K
417
559
end
418
560
561
+ """
562
+ pop!(collection, key[, default])
563
+
564
+ Delete and return the mapping for `key` if it exists in `collection`, otherwise return
565
+ `default`, or throw an error if `default` is not specified.
566
+
567
+ # Examples
568
+ ```jldoctest
569
+ julia> d = SwissDict("a"=>1, "b"=>2, "c"=>3);
570
+
571
+ julia> pop!(d, "a")
572
+ 1
573
+
574
+ julia> pop!(d, "d")
575
+ ERROR: KeyError: key "d" not found
576
+ Stacktrace:
577
+ [...]
578
+
579
+ julia> pop!(d, "e", 4)
580
+ 4
581
+ ```
582
+ """
583
+ pop! (collection, key, default)
584
+
419
585
function _pop! (h:: SwissDict , index)
420
586
@inbounds val = h. vals[index]
421
587
_delete! (h, index)
@@ -445,6 +611,23 @@ function pop!(h::SwissDict)
445
611
return key => val
446
612
end
447
613
614
+ """
615
+ delete!(collection, key)
616
+
617
+ Delete the mapping for the given key in a collection, and return the collection.
618
+
619
+ # Examples
620
+ ```jldoctest
621
+ julia> d = SwissDict("a"=>1, "b"=>2)
622
+ SwissDict{String,Int64} with 2 entries:
623
+ "b" => 2
624
+ "a" => 1
625
+
626
+ julia> delete!(d, "b")
627
+ SwissDict{String,Int64} with 1 entry:
628
+ "a" => 1
629
+ ```
630
+ """
448
631
function delete! (h:: SwissDict , key)
449
632
index = ht_keyindex (h, key)
450
633
if index > 0
0 commit comments