@@ -83,18 +83,33 @@ fun List<Row>.print(separator: String = "\t") = asSequence().print(separator)
8383/* * Internal representations for column selection indices. Usually not use directly but rather via [with] and [without].
8484 */
8585abstract class ColSelect (val indices : Array <Int > = emptyArray()) {
86+
87+ // irrespective of selection mode (positive or negative) indices must be positive in here
88+ init {
89+ stopIfNot(indices.all { it > 0 }) {
90+ " kscript.text.* is using 1-based arrays to ease awk transition, so indices must be strictly positive"
91+ }
92+ }
93+
8694 abstract fun and (column : Int ): ColSelect
8795 abstract fun and (range : IntRange ): ColSelect
96+ abstract fun process (lines : Sequence <Row >): Sequence <Row >
8897}
8998
90- class PosSelect (arrayOf : Array <Int >) : ColSelect(arrayOf ) {
99+ class PosSelect (columnIndices : Array <Int >) : ColSelect(columnIndices ) {
91100 override fun and (column : Int ) = PosSelect (arrayOf(* indices, column))
92101 override fun and (range : IntRange ) = PosSelect (arrayOf(* indices, * range.toList().toTypedArray()))
102+
103+ override fun process (lines : Sequence <Row >): Sequence <Row > = lines.map { row -> Row (indices.map { row[it] }) }
93104}
94105
95- class NegSelect (arrayOf : Array <Int >) : ColSelect(arrayOf ) {
106+ class NegSelect (columnIndices : Array <Int >) : ColSelect(columnIndices ) {
96107 override fun and (column : Int ) = NegSelect (arrayOf(* indices, column))
97108 override fun and (range : IntRange ) = NegSelect (arrayOf(* indices, * range.toList().toTypedArray()))
109+
110+ override fun process (lines : Sequence <Row >): Sequence <Row > = lines.map {
111+ Row (it.filterIndexed { index, _ -> ! indices.contains(index+ 1 ) })
112+ }
98113}
99114
100115/* * Starts building a column selection index. Both positive and negative indices are supported. */
@@ -116,24 +131,20 @@ fun Sequence<Row>.select(vararg colIndices: Int): Sequence<Row> {
116131 " Can not mix positive and negative selections"
117132 }
118133
119- val selector = if (isPositive) PosSelect (arrayOf(* colIndices.toTypedArray())) else NegSelect (arrayOf(* colIndices.toTypedArray()))
134+ val selector = if (isPositive) {
135+ PosSelect (arrayOf(* colIndices.toTypedArray()))
136+ } else {
137+ NegSelect (arrayOf(* colIndices.map { - it }.toTypedArray()))
138+ }
120139
121140 return select(selector)
122141}
123142
124- fun Sequence<Row>.select (columns : ColSelect ): Sequence <Row > {
143+ fun Sequence<Row>.select (columnSelector : ColSelect ): Sequence <Row > {
125144 // more efficient but does not allow to change the order
126- // return map { it.filterIndexed { index, _ -> retainColumn(columns, index + 1) } }
127-
128- stopIfNot(columns.indices.all { it != 0 }) { " kscript.text.* is using 1-based arrays to ease awk transition" }
145+ // return map { it.filterIndexed { index, _ -> retainColumn(columnSelector, index + 1) } }
129146
130- return if (columns is PosSelect ) {
131- // positive selection
132- map { row -> Row (columns.indices.map { row[it] }) }
133- } else {
134- // negative selection
135- map { Row (it.filterIndexed { index, _ -> ! columns.indices.contains(index) }) }
136- }
147+ return columnSelector.process(this )
137148}
138149
139150
0 commit comments