lib: add Array::* for repetitions
[nit.git] / lib / standard / collection / array.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2008 Floréal Morandat <morandat@lirmm.fr>
5 #
6 # This file is free software, which comes along with NIT. This software is
7 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
9 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
10 # is kept unaltered, and a notification of the changes is added.
11 # You are allowed to redistribute it and sell it, alone or is a part of
12 # another product.
13
14 # This module introduces the standard array structure.
15 # It also implements two other abstract collections : ArrayMap and ArraySet
16 module array
17
18 import abstract_collection
19
20 # One dimension array of objects.
21 abstract class AbstractArrayRead[E]
22 super SequenceRead[E]
23
24 redef var length = 0
25
26 redef fun is_empty do return _length == 0
27
28 redef fun has(item)
29 do
30 var i = 0
31 var l = length
32 while i < l do
33 if self[i] == item then return true
34 i += 1
35 end
36 return false
37 end
38
39 redef fun has_only(item)
40 do
41 var i = 0
42 var l = length
43 while i < l do
44 if self[i] != item then return false
45 i += 1
46 end
47 return true
48 end
49
50 redef fun count(item)
51 do
52 var res = 0
53 var i = 0
54 var l = length
55 while i < l do
56 if self[i] == item then res += 1
57 i += 1
58 end
59 return res
60 end
61
62 redef fun index_of(item) do return index_of_from(item, 0)
63
64 redef fun last_index_of(item: E): Int do return last_index_of_from(item, length-1)
65
66 redef fun index_of_from(item: E, pos: Int): Int
67 do
68 var i = pos
69 var len = length
70 while i < len do
71 if self[i] == item then
72 return i
73 end
74 i += 1
75 end
76 return -1
77 end
78
79 redef fun last_index_of_from(item: E, pos: Int): Int
80 do
81 var i = pos
82 while i >= 0 do
83 if self[i] == item then
84 return i
85 else
86 i -= 1
87 end
88 end
89 return -1
90 end
91
92 # Return a new array that is the reverse of `self`
93 #
94 # assert [1,2,3].reversed == [3, 2, 1]
95 fun reversed: Array[E]
96 do
97 var cmp = _length
98 var result = new Array[E].with_capacity(cmp)
99 while cmp > 0 do
100 cmp -= 1
101 result.add(self[cmp])
102 end
103 return result
104 end
105
106 # Copy a portion of `self` to an other array.
107 #
108 # var a = [1, 2, 3, 4]
109 # var b = [10, 20, 30, 40, 50]
110 # a.copy_to(1, 2, b, 2)
111 # assert b == [10, 20, 2, 3, 50]
112 protected fun copy_to(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
113 do
114 # TODO native one
115 var i = len
116 while i > 0 do
117 i -= 1
118 dest[new_start+i] = self[start+i]
119 end
120 end
121
122 redef fun output
123 do
124 var i = 0
125 var l = length
126 while i < l do
127 var e = self[i]
128 if e != null then e.output
129 i += 1
130 end
131 end
132
133 redef fun iterator: ArrayIterator[E] do return new ArrayIterator[E](self)
134 redef fun reverse_iterator do return new ArrayReverseIterator[E](self)
135 end
136
137 # Resizable one dimension array of objects.
138 abstract class AbstractArray[E]
139 super AbstractArrayRead[E]
140 super Sequence[E]
141
142 # Force the capacity to be at least `cap`.
143 # The capacity of the array is an internal information.
144 # However, this method can be used to prepare a large amount of add
145 fun enlarge(cap: Int) is abstract
146
147 redef fun push(item) do add(item)
148
149 redef fun pop
150 do
151 assert not_empty: not is_empty
152 var r = last
153 _length -= 1
154 return r
155 end
156
157 redef fun shift
158 do
159 assert not_empty: not is_empty
160 var r = first
161 var i = 1
162 var l = length
163 while i < l do
164 self[i-1] = self[i]
165 i += 1
166 end
167 _length = l - 1
168 return r
169 end
170
171 redef fun unshift(item)
172 do
173 var i = length - 1
174 while i >= 0 do
175 self[i+1] = self[i]
176 i -= 1
177 end
178 self[0] = item
179 end
180
181 redef fun insert(item: E, pos: Int)
182 do
183 enlarge(length + 1)
184 copy_to(pos, length-pos, self, pos + 1)
185 self[pos] = item
186 end
187
188 redef fun insert_all(coll, pos)
189 do
190 var l = coll.length
191 if l == 0 then return
192 enlarge(length + l)
193 _length += l
194 copy_to(pos, length-pos-l, self, pos + l)
195 for c in coll do
196 self[pos] = c
197 pos += 1
198 end
199 end
200
201 redef fun add(item) do self[length] = item
202
203 redef fun clear do _length = 0
204
205 redef fun remove(item) do remove_at(index_of(item))
206
207 redef fun remove_all(item)
208 do
209 var i = index_of(item)
210 while i >= 0 do
211 remove_at(i)
212 i = index_of_from(item, i)
213 end
214 end
215
216 redef fun remove_at(i)
217 do
218 var l = length
219 if i >= 0 and i < l then
220 var j = i + 1
221 while j < l do
222 self[j-1] = self[j]
223 j += 1
224 end
225 _length = l - 1
226 end
227 end
228
229 # Invert two elements in the array
230 #
231 # var a = [10, 20, 30, 40]
232 # a.swap_at(1, 3)
233 # assert a == [10, 40, 30, 20]
234 fun swap_at(a: Int,b: Int)
235 do
236 var e = self[a]
237 self[a] = self[b]
238 self[b] = e
239 end
240 end
241
242 # Resizable one dimension array of objects.
243 #
244 # Arrays have a literal representation.
245 # var a = [12, 32, 8]
246 # # is equivalent with:
247 # var b = new Array[Int]
248 # b.push(12)
249 # b.push(32)
250 # b.push(8)
251 # assert a == b
252 class Array[E]
253 super AbstractArray[E]
254 super ArrayCapable[E]
255
256 redef fun [](index)
257 do
258 assert index: index >= 0 and index < _length
259 return _items[index]
260 end
261
262 redef fun []=(index, item)
263 do
264 assert index: index >= 0 and index < _length + 1
265 if _capacity <= index then
266 enlarge(index + 1)
267 end
268 if _length <= index then
269 _length = index + 1
270 end
271 _items[index] = item
272 end
273
274 redef fun add(item)
275 do
276 var l = _length
277 if _capacity <= l then
278 enlarge(l + 1)
279 end
280 _length = l + 1
281 _items[l] = item
282 end
283
284 redef fun enlarge(cap)
285 do
286 var c = _capacity
287 if cap <= c then return
288 while c <= cap do c = c * 2 + 2
289 var a = calloc_array(c)
290 if _capacity > 0 then _items.copy_to(a, _length)
291 _items = a
292 _capacity = c
293 end
294
295 # Create an empty array.
296 init
297 do
298 _capacity = 0
299 _length = 0
300 end
301
302 # Create an array from a collection.
303 init from(items: Collection[E]) do
304 with_capacity(items.length)
305 self.add_all(items)
306 end
307
308 # Create an array with some `objects`.
309 init with_items(objects: E...)
310 do
311 _items = objects._items
312 _capacity = objects._capacity
313 _length = objects.length
314 end
315
316 # Create an empty array with a given capacity.
317 init with_capacity(cap: Int)
318 do
319 assert positive: cap >= 0
320 _items = calloc_array(cap)
321 _capacity = cap
322 _length = 0
323 end
324
325 # Create an array of `count` elements
326 init filled_with(value: E, count: Int)
327 do
328 assert positive: count >= 0
329 _items = calloc_array(count)
330 _capacity = count
331 _length = count
332 var i = 0
333 while i < count do
334 self[i] = value
335 i += 1
336 end
337 end
338
339 # Create a array filled with a given native array.
340 init with_native(nat: NativeArray[E], size: Int)
341 do
342 assert positive: size >= 0
343 _items = nat
344 _capacity = size
345 _length = size
346 end
347
348 # The internal storage.
349 private var items: nullable NativeArray[E] = null
350
351 # Do not use this method
352 # FIXME: Remove it once modules can intrude non local modules
353 fun intern_items: NativeArray[E] do return _items.as(not null)
354
355 # The size of `_items`.
356 private var capacity: Int = 0
357
358 redef fun ==(o)
359 do
360 if not o isa Array[nullable Object] then return super
361 # Efficient implementation
362 var l = length
363 if l != o.length then return false
364 var i = 0
365 var it = _items
366 var oit = o._items
367 while i < l do
368 if it[i] != oit[i] then return false
369 i += 1
370 end
371 return true
372 end
373
374 # Concatenation of arrays.
375 #
376 # Returns a new array built by concatenating `self` and `other` together.
377 #
378 # var a1 = [1,2,3]
379 # var a2 = [4,5,6]
380 # var a3 = a1 + a2
381 # assert a3 == [1,2,3,4,5,6]
382 #
383 # Because a new array is always created, future modification on `self` and `other`
384 # does not impact the previously computed result.
385 #
386 # a1.add(30)
387 # a2.add(60)
388 # assert a3 == [1,2,3,4,5,6] # unchanged
389 # assert a1 + a2 == [1,2,3,30,4,5,6,60]
390 fun +(other: Array[E]): Array[E]
391 do
392 var res = new Array[E].with_capacity(length + other.length)
393 res.append(self)
394 res.append(other)
395 return res
396 end
397
398 # Repetition of arrays.
399 #
400 # returns a new array built by concatenating `self` `repeat` times.
401 #
402 # var a = [1,2,3]
403 # assert (a * 0).is_empty
404 # assert a * 1 == [1,2,3]
405 # assert a * 2 == [1,2,3,1,2,3]
406 # assert (a * 10).length == 30
407 fun *(repeat: Int): Array[E]
408 do
409 assert repeat >= 0
410 var res = new Array[E].with_capacity(length * repeat)
411 while repeat > 0 do
412 res.add_all(self)
413 repeat -= 1
414 end
415 return res
416 end
417 end
418
419 # An `Iterator` on `AbstractArray`
420 private class ArrayIterator[E]
421 super IndexedIterator[E]
422
423 redef fun item do return _array[_index]
424
425 # redef fun item=(e) do _array[_index] = e
426
427 redef fun is_ok do return _index < _array.length
428
429 redef fun next do _index += 1
430
431 redef var index = 0
432
433 private var array: AbstractArrayRead[E]
434 end
435
436 private class ArrayReverseIterator[E]
437 super ArrayIterator[E]
438
439 redef fun is_ok do return _index >= 0
440
441 redef fun next do _index -= 1
442
443 init
444 do
445 _index = _array.length - 1
446 end
447 end
448
449 # Others collections ##########################################################
450
451 # A set implemented with an Array.
452 class ArraySet[E: Object]
453 super Set[E]
454
455 # The stored elements.
456 private var array: Array[E] is noinit
457
458 redef fun has(e) do return _array.has(e)
459
460 redef fun add(e) do if not _array.has(e) then _array.add(e)
461
462 redef fun is_empty do return _array.is_empty
463
464 redef fun length do return _array.length
465
466 redef fun first
467 do
468 assert _array.length > 0
469 return _array.first
470 end
471
472 redef fun remove(item)
473 do
474 var i = _array.index_of(item)
475 if i >= 0 then remove_at(i)
476 end
477
478 redef fun remove_all(item) do remove(item)
479
480 redef fun clear do _array.clear
481
482 redef fun iterator do return new ArraySetIterator[E](_array.iterator)
483
484 # Assume the capacity is at least `cap`.
485 fun enlarge(cap: Int) do _array.enlarge(cap)
486
487 private fun remove_at(i: Int)
488 do
489 _array[i] = _array.last
490 _array.pop
491 end
492
493 # Create an empty set
494 init do _array = new Array[E]
495
496 # Create an empty set with a given capacity.
497 init with_capacity(i: Int) do _array = new Array[E].with_capacity(i)
498
499 redef fun new_set do return new ArraySet[E]
500 end
501
502 # Iterators on sets implemented with arrays.
503 private class ArraySetIterator[E: Object]
504 super Iterator[E]
505
506 redef fun is_ok do return _iter.is_ok
507
508 redef fun next do _iter.next
509
510 redef fun item: E do return _iter.item
511
512 private var iter: ArrayIterator[E]
513 end
514
515
516 # Associative arrays implemented with an array of (key, value) pairs.
517 class ArrayMap[K: Object, E]
518 super CoupleMap[K, E]
519
520 # O(n)
521 redef fun [](key)
522 do
523 var i = index(key)
524 if i >= 0 then
525 return _items[i].second
526 else
527 return provide_default_value(key)
528 end
529 end
530
531 # O(n)
532 redef fun []=(key, item)
533 do
534 var i = index(key)
535 if i >= 0 then
536 _items[i].second = item
537 else
538 _items.push(new Couple[K,E](key, item))
539 end
540 end
541
542 redef var keys: RemovableCollection[K] = new ArrayMapKeys[K, E](self)
543 redef var values: RemovableCollection[E] = new ArrayMapValues[K, E](self)
544
545 # O(1)
546 redef fun length do return _items.length
547
548 redef fun couple_iterator do return _items.iterator
549
550 redef fun is_empty do return _items.is_empty
551
552 redef fun clear do _items.clear
553
554 # Assume the capacity to be at least `cap`.
555 fun enlarge(cap: Int) do _items.enlarge(cap)
556
557 redef fun couple_at(key)
558 do
559 var i = index(key)
560 if i >= 0 then
561 return _items[i]
562 else
563 return null
564 end
565 end
566
567 # Internal storage.
568 private var items = new Array[Couple[K,E]]
569
570 # fast remove the ith element of the array
571 private fun remove_at_index(i: Int)
572 do
573 _items[i] = _items.last
574 _items.pop
575 end
576
577 # The last positive result given by a index(1) call
578 private var last_index: Int = 0
579
580 # Where is the `key` in `_item`?
581 # return -1 if not found
582 private fun index(key: K): Int
583 do
584 var l = _last_index
585 if l < _items.length and _items[l].first == key then return l
586
587 var i = 0
588 while i < _items.length do
589 if _items[i].first == key then
590 _last_index = i
591 return i
592 end
593 i += 1
594 end
595 return -1
596 end
597 end
598
599 private class ArrayMapKeys[K: Object, E]
600 super RemovableCollection[K]
601 # The original map
602 var map: ArrayMap[K, E]
603 redef fun count(k) do if self.has(k) then return 1 else return 0
604 redef fun first do return self.map._items.first.first
605 redef fun has(k) do return self.map.index(k) >= 0
606 redef fun has_only(k) do return (self.has(k) and self.length == 1) or self.is_empty
607 redef fun is_empty do return self.map.is_empty
608 redef fun length do return self.map.length
609 redef fun iterator do return new MapKeysIterator[K, E](self.map.iterator)
610 redef fun clear do self.map.clear
611 redef fun remove(key)
612 do
613 var i = self.map.index(key)
614 if i >= 0 then self.map.remove_at_index(i)
615 end
616 redef fun remove_all(key) do self.remove(key)
617 end
618
619 private class ArrayMapValues[K: Object, E]
620 super RemovableCollection[E]
621 # The original map
622 var map: ArrayMap[K, E]
623 redef fun first do return self.map._items.first.second
624 redef fun is_empty do return self.map.is_empty
625 redef fun length do return self.map.length
626 redef fun iterator do return new MapValuesIterator[K, E](self.map.iterator)
627
628 # O(n)
629 redef fun has(item)
630 do
631 for i in self.map._items do if i.second == item then return true
632 return false
633 end
634
635 # O(n)
636 redef fun has_only(item)
637 do
638 for i in self.map._items do if i.second != item then return false
639 return true
640 end
641
642 # O(n)
643 redef fun count(item)
644 do
645 var nb = 0
646 for i in self.map._items do if i.second == item then nb += 1
647 return nb
648 end
649
650 redef fun clear do self.map.clear
651
652 redef fun remove(item)
653 do
654 var map = self.map
655 var i = map._items.length - 1
656 while i >= 0 do
657 if map._items[i].second == item then
658 map.remove_at_index(i)
659 return
660 end
661 i -= 1
662 end
663 end
664
665 redef fun remove_all(item)
666 do
667 var map = self.map
668 var i = map._items.length - 1
669 while i >= 0 do
670 if map._items[i].second == item then
671 map.remove_at_index(i)
672 end
673 i -= 1
674 end
675 end
676 end
677
678 # Comparable array for comparable elements.
679 #
680 # For two arrays, if one is a prefix, then it is lower.
681 #
682 # ~~~
683 # var a12 = new ArrayCmp[nullable Int].with_items(1,2)
684 # var a123 = new ArrayCmp[nullable Int].with_items(1,2,3)
685 # assert a12 < a123
686 # ~~~
687 #
688 # Otherwise, the first element just after the longest
689 # common prefix gives the order between the two arrays.
690 #
691 # ~~~
692 # var a124 = new ArrayCmp[nullable Int].with_items(1,2,4)
693 # var a13 = new ArrayCmp[nullable Int].with_items(1,3)
694 # assert a12 < a123
695 # assert a123 < a13
696 # ~~~
697 #
698 # Obviously, two equal arrays are equal.
699 #
700 # ~~~
701 # var b12 = new ArrayCmp[nullable Int].with_items(1,2)
702 # assert (a12 <=> b12) == 0
703 # ~~~
704 #
705 # `null` is considered lower than any other elements.
706 # But is still greater than no element.
707 #
708 # ~~~
709 # var a12n = new ArrayCmp[nullable Int].with_items(1,2,null)
710 # assert a12n < a123
711 # assert a12 < a12n
712 # ~~~
713 class ArrayCmp[E: nullable Comparable]
714 super Array[E]
715 super Comparable
716 redef type OTHER: ArrayCmp[E] is fixed
717
718 redef fun <(o) do return (self <=> o) < 0
719
720 redef fun <=>(o)
721 do
722 var it = _items
723 var oit = o._items
724 var i = 0
725 var l = length
726 var ol = o.length
727 var len
728 if l < ol then len = l else len = ol
729 while i < len do
730 var a = it[i]
731 var b = oit[i]
732 if a != null then
733 if b == null then return 1
734 var d = a <=> b.as(Comparable)
735 if d != 0 then return d
736 else
737 if b != null then return -1
738 end
739 i += 1
740 end
741 return l <=> ol
742 end
743 end
744
745 # Others tools ################################################################
746
747 redef class Iterator[E]
748 # Interate on `self` and build an array
749 fun to_a: Array[E]
750 do
751 var res = new Array[E]
752 while is_ok do
753 res.add(item)
754 next
755 end
756 return res
757 end
758 end
759
760 redef class Collection[E]
761 # Build a new array from a collection
762 fun to_a: Array[E]
763 do
764 var res = new Array[E].with_capacity(length)
765 res.add_all(self)
766 return res
767 end
768 end
769
770 # Native classes ##############################################################
771
772 # Subclasses of this class can create native arrays
773 interface ArrayCapable[E]
774 # Get a new array of `size` elements.
775 protected fun calloc_array(size: Int): NativeArray[E] is intern
776 end
777
778 # Native Nit array
779 # Access are unchecked and it has a fixed size
780 # Not for public use: may become private.
781 universal NativeArray[E]
782 # Creates a new NativeArray of capacity `length`
783 new(length: Int) is intern
784 # The length of the array
785 fun length: Int is intern
786 # Use `self` to initialize a standard Nit Array.
787 fun to_a: Array[E] do return new Array[E].with_native(self, length)
788 fun [](index: Int): E is intern
789 fun []=(index: Int, item: E) is intern
790 fun copy_to(dest: NativeArray[E], length: Int) is intern
791 #fun =(o: NativeArray[E]): Bool is intern
792 #fun !=(o: NativeArray[E]): Bool is intern
793 end