494 |
498 |
495 srcIndex1 := firstIndex. |
499 srcIndex1 := firstIndex. |
496 last1 := srcIndex1 + n1 -1. |
500 last1 := srcIndex1 + n1 -1. |
497 |
501 |
498 (srcIndex1 <= last1 and:[srcIndex2 <= last2]) ifTrue:[ |
502 (srcIndex1 <= last1 and:[srcIndex2 <= last2]) ifTrue:[ |
499 el1 := contentsArray at:srcIndex1. |
503 el1 := contentsArray basicAt:srcIndex1. |
500 el2 := contentsArray2 at:srcIndex2. |
504 el2 := contentsArray2 basicAt:srcIndex2. |
501 end1Reached := end2Reached := false. |
505 end1Reached := end2Reached := false. |
502 |
506 |
503 [end1Reached or:[end2Reached]] whileFalse:[ |
507 [end1Reached or:[end2Reached]] whileFalse:[ |
504 (sortBlock value:el1 value:el2) ifTrue:[ |
508 (sortBlock value:el1 value:el2) ifTrue:[ |
505 "/ el1 to come before el2 |
509 "/ el1 to come before el2 |
506 newContentsArray at:destIndex put:el1. destIndex := destIndex + 1. |
510 newContentsArray basicAt:destIndex put:el1. destIndex := destIndex + 1. |
507 srcIndex1 := srcIndex1 + 1. |
511 srcIndex1 := srcIndex1 + 1. |
508 srcIndex1 <= last1 ifTrue:[ |
512 srcIndex1 <= last1 ifTrue:[ |
509 el1 := contentsArray at:srcIndex1. |
513 el1 := contentsArray basicAt:srcIndex1. |
510 ] ifFalse:[ |
514 ] ifFalse:[ |
511 end1Reached := true |
515 end1Reached := true |
512 ] |
516 ] |
513 ] ifFalse:[ |
517 ] ifFalse:[ |
514 "/ el2 to come before el1 |
518 "/ el2 to come before el1 |
515 newContentsArray at:destIndex put:el2. destIndex := destIndex + 1. |
519 newContentsArray basicAt:destIndex put:el2. destIndex := destIndex + 1. |
516 srcIndex2 := srcIndex2 + 1. |
520 srcIndex2 := srcIndex2 + 1. |
517 srcIndex2 <= last2 ifTrue:[ |
521 srcIndex2 <= last2 ifTrue:[ |
518 el2 := contentsArray2 at:srcIndex2. |
522 el2 := contentsArray2 basicAt:srcIndex2. |
519 ] ifFalse:[ |
523 ] ifFalse:[ |
520 end2Reached := true |
524 end2Reached := true |
521 ] |
525 ] |
522 ] |
526 ] |
523 ] |
527 ] |
740 exceptionBlock." |
790 exceptionBlock." |
741 |
791 |
742 |index "{ Class: SmallInteger }" |
792 |index "{ Class: SmallInteger }" |
743 last "{ Class: SmallInteger }"| |
793 last "{ Class: SmallInteger }"| |
744 |
794 |
745 index := self indexForInserting:anObject. |
795 index := self indexOf:anObject. |
746 ((index < firstIndex) |
796 index == 0 ifTrue:[ |
747 or:[(contentsArray at:index) ~= anObject]) ifTrue:[^ exceptionBlock value]. |
797 ^ exceptionBlock value. |
|
798 ]. |
748 |
799 |
749 "skip multiple occurrences of the same ..." |
800 "skip multiple occurrences of the same ..." |
750 |
801 index := index + firstIndex - 1. |
751 last := lastIndex. |
802 last := lastIndex. |
752 [(index <= last) and:[(contentsArray at:index) = anObject]] whileTrue:[ |
803 [(index <= last) and:[(contentsArray basicAt:index) = anObject]] whileTrue:[ |
753 index := index + 1 |
804 index := index + 1 |
754 ]. |
805 ]. |
755 (index > last) ifTrue:[^ nil]. |
806 (index > last) ifTrue:[^ exceptionBlock value]. |
756 ^ contentsArray at:index |
807 ^ contentsArray basicAt:index |
757 |
808 |
758 "Modified: 12.4.1996 / 13:20:33 / cg" |
809 " |
|
810 #(7 3 9 10 99) asSortedCollection after:50 |
|
811 #(7 3 9 10 99) asSortedCollection after:3 |
|
812 #(7 3 9 10 99) asSortedCollection after:1 |
|
813 #(7 3 9 10 99) asSortedCollection after:10 |
|
814 #(7 3 9 10 99) asSortedCollection after:7 |
|
815 #(7 3 9 10 99) asSortedCollection after:99 |
|
816 #(7 10 3 10 9 10 10 99) asSortedCollection after:9 |
|
817 #(7 10 3 10 9 10 10 99) asSortedCollection after:10 |
|
818 " |
759 ! |
819 ! |
760 |
820 |
761 before:anObject ifAbsent:exceptionBlock |
821 before:anObject ifAbsent:exceptionBlock |
762 "return the element before the argument, anObject; or nil if there is none. |
822 "return the element before the argument, anObject; or nil if there is none. |
763 If the receiver does not contain anObject, return the result from evaluating |
823 If the receiver does not contain anObject, return the result from evaluating |
764 exceptionBlock." |
824 exceptionBlock." |
765 |
825 |
766 |index "{ Class: SmallInteger }"| |
826 |index "{ Class: SmallInteger }"| |
767 |
827 |
768 index := self indexForInserting:anObject. |
828 index := self indexOf:anObject. |
769 ((index <= firstIndex) |
829 index <= 1 ifTrue:[ |
770 or:[(contentsArray at:index) ~= anObject]) ifTrue:[^ exceptionBlock value]. |
830 ^ exceptionBlock value. |
771 |
831 ]. |
772 ^ contentsArray at:index - 1 |
832 ^ contentsArray basicAt:firstIndex + index - 2 |
773 |
833 |
774 " |
834 " |
775 #(7 3 9 10 99) asSortedCollection before:50 |
835 #(7 3 9 10 99) asSortedCollection before:50 |
|
836 #(7 3 9 10 99) asSortedCollection before:3 |
776 #(7 3 9 10 99) asSortedCollection before:1 |
837 #(7 3 9 10 99) asSortedCollection before:1 |
777 #(7 3 9 10 99) asSortedCollection before:10 |
838 #(7 3 9 10 99) asSortedCollection before:10 |
778 #(7 3 9 10 99) asSortedCollection before:7 |
839 #(7 3 9 10 99) asSortedCollection before:7 |
779 #(7 3 9 10 99) asSortedCollection before:99 |
840 #(7 3 9 10 99) asSortedCollection before:99 |
780 #(7 10 3 10 9 10 10 99) asSortedCollection before:9 |
841 #(7 10 3 10 9 10 10 99) asSortedCollection before:9 |
781 #(7 10 3 10 9 10 10 99) asSortedCollection before:10 |
842 #(7 10 3 10 9 10 10 99) asSortedCollection before:10 |
782 " |
843 " |
783 ! |
844 ! |
784 |
845 |
785 indexForInserting:anObject |
846 indexOf:anObject |
786 "search the index at which to insert anObject. |
847 "return true, if the argument, anObject is in the collection. |
787 Can also be used to search for an existing element |
848 Redefined, since due to being sorted, the inclusion check can |
788 by checking if the element at the returned index is the one we look for. |
849 be done with log-n compares i.e. much faster." |
789 Uses a binarySearch since we can depend on the elements being in sorted order. |
850 |
790 The returned index is a physical one, for accessing contentsArray." |
851 |index "{ Class: SmallInteger }" |
791 |
852 initialIndex "{ Class: SmallInteger }" |
792 |low "{ Class: SmallInteger}" |
|
793 high "{ Class: SmallInteger}" |
|
794 middle "{ Class: SmallInteger}" |
|
795 element| |
853 element| |
796 |
854 |
797 " |
855 "/ if I am small, the inherited linear search is faster ... |
798 we can of course use a binary search - since the elements are sorted |
856 (lastIndex - firstIndex) < 20 ifTrue:[ |
799 " |
857 firstIndex > lastIndex ifTrue:[ |
800 low := firstIndex. |
858 "/ empty |
801 high := lastIndex. |
859 ^ 0 |
802 [low > high] whileFalse:[ |
860 ]. |
803 middle := (low + high) // 2. |
861 ^ super indexOf:anObject. |
804 element := contentsArray at:middle. |
862 ]. |
805 (sortBlock value:element value:anObject) ifTrue:[ |
863 |
806 "middleelement is smaller than object" |
864 initialIndex := self indexForInserting:anObject. |
807 low := middle + 1 |
865 initialIndex > lastIndex ifTrue:[ |
808 ] ifFalse:[ |
866 initialIndex := lastIndex |
809 high := middle - 1 |
867 ] ifFalse:[ |
|
868 initialIndex < firstIndex ifTrue:[ |
|
869 initialIndex := firstIndex |
810 ] |
870 ] |
811 ]. |
871 ]. |
812 ^ low |
872 |
813 |
873 "the complex case: the collection may include elements, which are odered only by |
814 " |
874 a single component (e.g. Associations by key). So we have to test all |
815 #(1 2 3 4 7 99 1313 981989 898989898) asSortedCollection indexForInserting:50 |
875 previous and next elements having the same component" |
816 |
876 |
817 #(1.0 2.0 3 4 7 49.0 51.0 99 1313 981989 898989898) asSortedCollection indexForInserting:50 |
877 "for previous elements: while element is not smaller and not larger than anObject ... compare" |
818 |
878 index := initialIndex. |
819 " |
879 [index >= firstIndex |
820 |
880 and:[ |
821 "Modified: 12.4.1996 / 13:22:03 / cg" |
881 element := contentsArray basicAt:index. |
822 ! |
882 ((sortBlock value:element value:anObject) or:[sortBlock value:anObject value:element]) not] |
823 |
883 ] whileTrue:[ |
824 indexOf:anElement |
884 element = anObject ifTrue:[ |
825 "Return the index of anElement within the receiver. |
885 ^ index - firstIndex + 1. |
826 If the receiver does not contain anElement, return 0." |
886 ]. |
827 |
887 index := index - 1. |
828 ^ self indexOf:anElement ifAbsent:0 |
888 ]. |
|
889 |
|
890 "for next elements: while element is not smaller and not larger than anObject ... compare" |
|
891 index := initialIndex. |
|
892 [index <= lastIndex |
|
893 and:[ |
|
894 element := contentsArray basicAt:index. |
|
895 ((sortBlock value:element value:anObject) or:[sortBlock value:anObject value:element]) not] |
|
896 ] whileTrue:[ |
|
897 element = anObject ifTrue:[ |
|
898 ^ index - firstIndex + 1. |
|
899 ]. |
|
900 index := index + 1. |
|
901 ]. |
|
902 |
|
903 ^ 0. |
|
904 |
|
905 " |
|
906 #(7 3 9 10 99) asSortedCollection indexOf:50 |
|
907 #(7 3 9 10 99) asSortedCollection indexOf:10 |
|
908 |
|
909 #('aa' 'bb' 'cc' 'dd') asSortedCollection indexOf:'bb' |
|
910 #('aa' 'bb' 'cc' 'dd' 'aa' 'bb' 'cc' 'dd') asSortedCollection indexOf:'bb' |
|
911 |
|
912 |allSyms indices| |
|
913 allSyms := Symbol allInstances asSortedCollection. |
|
914 Time millisecondsToRun:[ |
|
915 indices := allSyms collect:[:el | allSyms indexOf:el]. |
|
916 ]. |
|
917 indices = (1 to:allSyms size) |
|
918 " |
829 ! |
919 ! |
830 |
920 |
831 indexOf:anElement ifAbsent:exceptionBlock |
921 indexOf:anElement ifAbsent:exceptionBlock |
832 "Return the index of anElement within the receiver. |
922 "Return the index of anElement within the receiver. |
833 If the receiver does not contain anElement, |
923 If the receiver does not contain anElement, |
834 return the result of evaluating the argument, exceptionBlock." |
924 return the result of evaluating the argument, exceptionBlock." |
835 |
925 |
836 |insertionIndex index "{ Class: SmallInteger }" |
926 |idx| |
837 obj| |
927 |
838 |
928 idx := self indexOf:anElement. |
839 firstIndex > lastIndex ifTrue:[ |
929 idx == 0 ifTrue:[^ exceptionBlock value]. |
840 "/ empty |
930 ^ idx. |
841 ^ exceptionBlock value |
|
842 ]. |
|
843 |
|
844 "/ if I am small, the inherited linear search is faster ... |
|
845 (lastIndex - firstIndex) < 20 ifTrue:[ |
|
846 ^ super indexOf:anElement ifAbsent:exceptionBlock |
|
847 ]. |
|
848 |
|
849 insertionIndex := self indexForInserting:anElement. |
|
850 insertionIndex > lastIndex ifTrue:[ |
|
851 insertionIndex := lastIndex |
|
852 ] ifFalse:[ |
|
853 insertionIndex < firstIndex ifTrue:[ |
|
854 insertionIndex := firstIndex |
|
855 ] |
|
856 ]. |
|
857 |
|
858 index := insertionIndex. |
|
859 [index >= firstIndex |
|
860 and:[obj := contentsArray basicAt:index. |
|
861 anElement = obj ifTrue: [^ index - firstIndex + 1]. |
|
862 [sortBlock value:anElement value:obj]]] |
|
863 whileTrue: [index := index - 1]. |
|
864 |
|
865 index := insertionIndex. |
|
866 [index <= lastIndex |
|
867 and: [obj := contentsArray basicAt: index. |
|
868 anElement = obj ifTrue: [^ index - firstIndex + 1]. |
|
869 [sortBlock value:obj value:anElement]]] |
|
870 whileTrue: [index := index + 1]. |
|
871 |
|
872 ^exceptionBlock value |
|
873 |
|
874 " |
|
875 #('aa' 'bb' 'cc' 'dd') asSortedCollection indexOf:'bb' |
|
876 #('aa' 'bb' 'cc' 'dd' 'aa' 'bb' 'cc' 'dd') asSortedCollection indexOf:'bb' |
|
877 |
|
878 |allSyms indices| |
|
879 allSyms := Symbol allInstances asSortedCollection. |
|
880 Time millisecondsToRun:[ |
|
881 indices := allSyms collect:[:el | allSyms indexOf:el]. |
|
882 ]. |
|
883 indices = (1 to:allSyms size) |
|
884 " |
|
885 ! |
931 ! |
886 |
932 |
887 largest:n |
933 largest:n |
888 "return a collection containing the n largest elements, largest last. |
934 "return a collection containing the n largest elements, largest last. |
889 Raises an exception, if the receiver does not contain at least n elements" |
935 Raises an exception, if the receiver does not contain at least n elements" |
978 includes:anObject |
1024 includes:anObject |
979 "return true, if the argument, anObject is in the collection. |
1025 "return true, if the argument, anObject is in the collection. |
980 Redefined, since due to being sorted, the inclusion check can |
1026 Redefined, since due to being sorted, the inclusion check can |
981 be done with log-n compares i.e. much faster." |
1027 be done with log-n compares i.e. much faster." |
982 |
1028 |
983 |index "{ Class: SmallInteger }"| |
1029 |index "{ Class: SmallInteger }" |
984 |
1030 initialIndex "{ Class: SmallInteger }" |
985 index := self indexForInserting:anObject. |
1031 element| |
986 ((index < firstIndex) or:[index > lastIndex]) ifTrue:[^ false]. |
1032 |
987 ^ (contentsArray at:index) = anObject |
1033 "/ if I am small, the inherited linear search is faster ... |
|
1034 (lastIndex - firstIndex) < 20 ifTrue:[ |
|
1035 firstIndex > lastIndex ifTrue:[ |
|
1036 "/ empty |
|
1037 ^ false |
|
1038 ]. |
|
1039 ^ super includes:anObject. |
|
1040 ]. |
|
1041 |
|
1042 initialIndex := self indexForInserting:anObject. |
|
1043 ((initialIndex < firstIndex) or:[initialIndex > lastIndex]) ifTrue:[^ false]. |
|
1044 (contentsArray basicAt:initialIndex) = anObject ifTrue:[ |
|
1045 "the simple case - plain objects" |
|
1046 ^ true. |
|
1047 ]. |
|
1048 |
|
1049 "the complex case: the collection may include elements, which are odered only by |
|
1050 a single component (e.g. Associations by key). So we have to test all |
|
1051 previous and next elements having the same component" |
|
1052 |
|
1053 "for previous elements: while element is not smaller and not larger than anObject ... compare" |
|
1054 index := initialIndex - 1. |
|
1055 [index >= firstIndex |
|
1056 and:[ |
|
1057 element := contentsArray basicAt:index. |
|
1058 ((sortBlock value:element value:anObject) or:[sortBlock value:anObject value:element]) not] |
|
1059 ] whileTrue:[ |
|
1060 element = anObject ifTrue:[ |
|
1061 ^ true. |
|
1062 ]. |
|
1063 index := index - 1. |
|
1064 ]. |
|
1065 |
|
1066 "for next elements: while element is not smaller and not larger than anObject ... compare" |
|
1067 index := initialIndex + 1. |
|
1068 [index <= lastIndex |
|
1069 and:[ |
|
1070 element := contentsArray basicAt:index. |
|
1071 ((sortBlock value:element value:anObject) or:[sortBlock value:anObject value:element]) not] |
|
1072 ] whileTrue:[ |
|
1073 element = anObject ifTrue:[ |
|
1074 ^ true. |
|
1075 ]. |
|
1076 index := index + 1. |
|
1077 ]. |
|
1078 |
|
1079 ^ false. |
988 |
1080 |
989 " |
1081 " |
990 #(7 3 9 10 99) asSortedCollection includes:50 |
1082 #(7 3 9 10 99) asSortedCollection includes:50 |
991 #(7 3 9 10 99) asSortedCollection includes:10 |
1083 #(7 3 9 10 99) asSortedCollection includes:10 |
992 " |
1084 " |