549 The argument, aBlock is evaluated for successive elements and all those, |
549 The argument, aBlock is evaluated for successive elements and all those, |
550 for which it returns true, are removed. |
550 for which it returns true, are removed. |
551 Return a collection containing the removed elements. |
551 Return a collection containing the removed elements. |
552 |
552 |
553 Performance hint: |
553 Performance hint: |
554 if a big number of objects is removed this way, |
554 if a large number of objects is to be removed this way, |
555 it may be better to rebuild a new collection via #select:, |
555 it may be better to rebuild a new collection via #select:, |
556 since removing elements out of the middle is somewhat slow |
556 since removing elements out of the middle is somewhat slow |
557 due to the need to copy over remaining elements within the collection." |
557 due to the need to copy over remaining elements within the collection." |
558 |
558 |
559 "/ this is a q&d implementation (possibly slow). |
559 "/ this is a q&d implementation (possibly slow). |
560 |
560 |
561 |runIndex removed element| |
561 |runIndex removed element sz| |
562 |
562 |
563 removed := self species new. |
563 removed := self species new. |
564 |
564 |
565 runIndex := 1. |
565 runIndex := 1. |
566 [runIndex <= self size] whileTrue:[ |
566 sz := self size. |
|
567 [runIndex <= sz] whileTrue:[ |
567 element := self at:runIndex. |
568 element := self at:runIndex. |
568 (aBlock value:element) ifTrue:[ |
569 (aBlock value:element) ifTrue:[ |
569 removed add:element. |
570 removed add:element. |
570 self removeAtIndex:runIndex |
571 self removeAtIndex:runIndex. |
|
572 sz := sz - 1. |
571 ] ifFalse:[ |
573 ] ifFalse:[ |
572 runIndex := runIndex + 1 |
574 runIndex := runIndex + 1 |
573 ] |
575 ] |
574 ]. |
576 ]. |
575 ^ removed |
577 ^ removed |
580 coll := OrderedCollection withAll:(1 to:10). |
582 coll := OrderedCollection withAll:(1 to:10). |
581 Transcript showCR:(coll removeAllSuchThat:[:el | el even]). |
583 Transcript showCR:(coll removeAllSuchThat:[:el | el even]). |
582 Transcript showCR:coll |
584 Transcript showCR:coll |
583 " |
585 " |
584 |
586 |
585 "Modified: 12.4.1996 / 13:37:01 / cg" |
587 "Modified: 8.2.1997 / 19:19:00 / cg" |
586 ! |
588 ! |
587 |
589 |
588 removeFirst |
590 removeFirst |
589 "remove the first element from the collection; return the element." |
591 "remove the first element from the collection; return the element." |
590 |
592 |
591 |anObject | |
593 |anObject fI "{ Class: SmallInteger }" | |
592 |
594 |
593 firstIndex > lastIndex ifTrue:[ |
595 fI := firstIndex. |
|
596 |
|
597 fI > lastIndex ifTrue:[ |
594 "error if collection is empty" |
598 "error if collection is empty" |
595 ^ self emptyCollectionError. |
599 ^ self emptyCollectionError. |
596 ]. |
600 ]. |
597 |
601 |
598 anObject := contentsArray at:firstIndex. |
602 anObject := contentsArray at:fI. |
599 |
603 |
600 "/ nil it out, to allow GC to reclaim it. |
604 "/ nil it out, to allow GC to reclaim it. |
601 contentsArray at:firstIndex put:nil. |
605 contentsArray at:fI put:nil. |
602 |
606 |
603 firstIndex := firstIndex + 1. |
607 fI := fI + 1. |
604 |
608 |
605 firstIndex > lastIndex ifTrue:[ |
609 fI > lastIndex ifTrue:[ |
606 "reset to avoid ever growing" |
610 "reset to avoid ever growing" |
607 firstIndex := 1. |
611 fI := 1. |
608 lastIndex := 0 |
612 lastIndex := 0 |
609 ]. |
613 ]. |
|
614 firstIndex := fI. |
610 ^ anObject |
615 ^ anObject |
611 |
616 |
612 " |
617 " |
613 (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst; yourself |
618 (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst; yourself |
614 OrderedCollection new removeFirst |
619 OrderedCollection new removeFirst |
615 (SortedCollection withAll:#(5 4 3 2 1)) removeFirst; yourself |
620 (SortedCollection withAll:#(5 4 3 2 1)) removeFirst; yourself |
616 " |
621 " |
617 |
622 |
618 "Modified: 1.2.1997 / 12:30:50 / cg" |
623 "Modified: 8.2.1997 / 19:14:39 / cg" |
619 ! |
624 ! |
620 |
625 |
621 removeFirst:n |
626 removeFirst:n |
622 "remove the first n elements from the collection; |
627 "remove the first n elements from the collection; |
623 Return a collection containing the removed elements." |
628 Return a collection containing the removed elements." |
624 |
629 |
625 |mySize ret| |
630 |mySize ret newFirstIndex| |
626 |
631 |
627 mySize := self size. |
632 mySize := self size. |
628 mySize < n ifTrue:[ |
633 mySize < n ifTrue:[ |
629 "error if collection has not enough elements" |
634 "error if collection has not enough elements" |
630 ^ self notEnoughElementsError. |
635 ^ self notEnoughElementsError. |
634 ret replaceFrom:1 to:n with:contentsArray startingAt:firstIndex. |
639 ret replaceFrom:1 to:n with:contentsArray startingAt:firstIndex. |
635 |
640 |
636 "/ |
641 "/ |
637 "/ nil-out contents array, to not keep elements from being GC'd |
642 "/ nil-out contents array, to not keep elements from being GC'd |
638 "/ |
643 "/ |
639 contentsArray from:firstIndex to:firstIndex + n - 1 put:nil. |
644 newFirstIndex := firstIndex + n. |
640 firstIndex := firstIndex + n. |
645 contentsArray from:firstIndex to:newFirstIndex - 1 put:nil. |
641 |
646 |
642 firstIndex > lastIndex ifTrue:[ |
647 newFirstIndex > lastIndex ifTrue:[ |
643 "reset to avoid ever growing" |
648 "reset to avoid ever growing" |
644 firstIndex := 1. |
649 newFirstIndex := 1. |
645 lastIndex := 0 |
650 lastIndex := 0 |
646 ]. |
651 ]. |
|
652 firstIndex := newFirstIndex. |
647 ^ ret |
653 ^ ret |
648 |
654 |
649 " |
655 " |
650 (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:2; yourself |
656 (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:2; yourself |
651 (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:0; yourself |
657 (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:0; yourself |
652 OrderedCollection new removeFirst:2 |
658 OrderedCollection new removeFirst:2 |
653 (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:6 |
659 (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:6 |
654 (SortedCollection withAll:#(5 4 3 2 1)) removeFirst:2; yourself |
660 (SortedCollection withAll:#(5 4 3 2 1)) removeFirst:2; yourself |
655 " |
661 " |
656 |
662 |
657 "Modified: 12.4.1996 / 13:37:39 / cg" |
663 "Modified: 8.2.1997 / 19:20:18 / cg" |
658 ! |
664 ! |
659 |
665 |
660 removeFromIndex:startIndex toIndex:stopIndex |
666 removeFromIndex:startIndex toIndex:stopIndex |
661 "remove the elements stored under startIndex up to and including |
667 "remove the elements stored under startIndex up to and including |
662 the elements under stopIndex. |
668 the elements under stopIndex. |
663 Return the receiver. |
669 Return the receiver. |
664 Returning the receiver here is a historic leftover - it may change. |
670 Returning the receiver here is a historic leftover - it may change. |
665 Please use yourself in a cascade, if you need the receivers value |
671 Please use yourself in a cascade, if you need the receivers value |
666 when using this method." |
672 when using this method." |
667 |
673 |
668 |nDeleted| |
674 |nDeleted "{ Class: SmallInteger }" |
|
675 newLastIndex| |
669 |
676 |
670 (startIndex < 1 |
677 (startIndex < 1 |
671 or:[stopIndex > self size]) ifTrue:[ |
678 or:[stopIndex > self size]) ifTrue:[ |
672 ^ self notEnoughElementsError |
679 ^ self notEnoughElementsError |
673 ]. |
680 ]. |
674 |
681 |
675 stopIndex < startIndex ifTrue:[ |
682 nDeleted := stopIndex - startIndex + 1. |
|
683 nDeleted < 0 ifTrue:[ |
676 "/ mhmh - what should be done here ? |
684 "/ mhmh - what should be done here ? |
677 ^ self error:'bad index range' |
685 ^ self error:'bad index range' |
678 ]. |
686 ]. |
679 |
687 nDeleted == 0 ifTrue:[^ self]. |
680 nDeleted := stopIndex - startIndex + 1. |
688 |
681 |
689 "/ |
682 "/ can be done faster, when removing the first elements |
690 "/ can be done faster, when removing the first elements |
|
691 "/ |
683 startIndex == firstIndex ifTrue:[ |
692 startIndex == firstIndex ifTrue:[ |
684 "/ nil out (helps GC) |
693 "/ nil out (helps GC) |
685 contentsArray |
694 contentsArray |
686 from:firstIndex |
695 from:firstIndex |
687 to:firstIndex + nDeleted - 1 |
696 to:firstIndex + nDeleted - 1 |
688 put:nil. |
697 put:nil. |
689 firstIndex := firstIndex + nDeleted |
698 firstIndex := firstIndex + nDeleted |
690 ] ifFalse:[ |
699 ] ifFalse:[ |
691 "/ can be done faster, when removinf the last elements |
700 "/ |
|
701 "/ can be done faster, when removing the last elements |
|
702 "/ |
692 stopIndex == lastIndex ifTrue:[ |
703 stopIndex == lastIndex ifTrue:[ |
693 "/ nil out (helps GC) |
704 "/ nil out (helps GC) |
694 contentsArray |
705 contentsArray |
695 from:lastIndex - nDeleted + 1 |
706 from:lastIndex - nDeleted + 1 |
696 to:lastIndex |
707 to:lastIndex |
697 put:nil. |
708 put:nil. |
698 lastIndex := lastIndex - nDeleted |
709 lastIndex := lastIndex - nDeleted |
699 ] ifFalse:[ |
710 ] ifFalse:[ |
|
711 "/ |
700 "/ must shuffle |
712 "/ must shuffle |
701 "/ TODO: |
713 "/ TODO: |
702 "/ for big collections, try to copy the smallest |
714 "/ for big collections, try to copy the smallest |
703 "/ possible number of elements |
715 "/ possible number of elements |
704 |
716 |
|
717 newLastIndex := lastIndex - nDeleted. |
|
718 |
705 contentsArray |
719 contentsArray |
706 replaceFrom:(firstIndex + startIndex - 1) |
720 replaceFrom:(firstIndex + startIndex - 1) |
707 to:(lastIndex - nDeleted) |
721 to:newLastIndex |
708 with:contentsArray |
722 with:contentsArray |
709 startingAt:(firstIndex + stopIndex). |
723 startingAt:(firstIndex + stopIndex). |
710 |
724 |
711 "/ nil out rest (helps GC) |
725 "/ nil out rest (helps GC) |
712 contentsArray |
726 contentsArray |
713 from:(lastIndex - nDeleted + 1) |
727 from:(newLastIndex + 1) |
714 to:lastIndex |
728 to:lastIndex |
715 put:nil. |
729 put:nil. |
716 |
730 |
717 lastIndex := lastIndex - nDeleted. |
731 lastIndex := newLastIndex. |
718 ] |
732 ] |
719 ]. |
733 ]. |
720 |
734 |
721 firstIndex > lastIndex ifTrue:[ |
735 firstIndex > lastIndex ifTrue:[ |
722 "reset to avoid ever growing" |
736 "reset to avoid ever growing" |