slice can accept negative indices
This commit is contained in:
1 parent
386afc1079
commit
7ad6de64ff
4 files changed
+37
-45
No files matched your search
@@ -170,14 +170,21 @@ split('\\.','foo.bar') => [foo, bar]
|
|||||||
### `slice(expr, from, to?)`
|
### `slice(expr, from, to?)`
|
||||||
|
|
||||||
extracts a substring, or sublist (based on the type of the result of the expression under expr with
|
extracts a substring, or sublist (based on the type of the result of the expression under expr with
|
||||||
starting index of `from`, and ending at `to` if provided, or the end, if omitted
|
starting index of `from`, and ending at `to` if provided, or the end, if omitted. Can use negative indices to
|
||||||
|
indicate counting form the back of the list, so `-1 <=> length(_)`.
|
||||||
|
|
||||||
|
Special case is made for iterators (`range`, `rect` etc), which does require non-negative indices (negative `from` is treated as
|
||||||
|
`0`, and negative `to` as `inf`), but allows retrieving parts of the sequence and ignore
|
||||||
|
other parts. In that case consecutive calls to `slice` will refer to index `0` the current iteration position since iterators
|
||||||
|
cannot go back nor track where they are in the sequence (see examples).
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
slice(l(0,1,2,3,4,5), 1, 3) => [1, 2, 3]
|
slice([0,1,2,3,4,5], 1, 3) => [1, 2, 3]
|
||||||
slice('foobar', 0, 1) => 'f'
|
slice('foobar', 0, 1) => 'f'
|
||||||
slice('foobar', 3) => 'bar'
|
slice('foobar', 3) => 'bar'
|
||||||
slice(range(10), 3, 5) => [3, 4, 5]
|
slice(range(10), 3, 5) => [3, 4, 5]
|
||||||
slice(range(10), 5) => [5, 6, 7, 8, 9]
|
slice(range(10), 5) => [5, 6, 7, 8, 9]
|
||||||
|
r = range(100); [slice(r, 5, 7), slice(r, 1, 3)] => [[5, 6], [8, 9]]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### `sort(list), sort(values ...)`
|
### `sort(list), sort(values ...)`
|
||||||
|
|||||||
@@ -289,27 +289,22 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
items.add(v);
|
items.add(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAtIndex(int index, List<Value> subList)
|
/**
|
||||||
|
* Finds a proper list index >=0 and < len that correspont to the rolling index value of idx
|
||||||
|
*
|
||||||
|
* @param idx
|
||||||
|
* @param len
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int normalizeIndex(long idx, int len)
|
||||||
{
|
{
|
||||||
int numitems = items.size();
|
if (idx >=0 && idx < len) return (int)idx;
|
||||||
long range = abs(index)/numitems;
|
long range = abs(idx)/len;
|
||||||
index += (range+2)*numitems;
|
idx += (range+2)*len;
|
||||||
index = index % numitems;
|
idx = idx % len;
|
||||||
for (Value v: subList)
|
return (int)idx;
|
||||||
{
|
|
||||||
if (index < numitems)
|
|
||||||
{
|
|
||||||
items.set(index, v);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
items.add(v);
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class ListConstructorValue extends ListValue
|
public static class ListConstructorValue extends ListValue
|
||||||
{
|
{
|
||||||
public ListConstructorValue(Collection<? extends Value> list)
|
public ListConstructorValue(Collection<? extends Value> list)
|
||||||
@@ -339,15 +334,15 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value slice(long from, long to)
|
public Value slice(long fromDesc, long toDesc)
|
||||||
{
|
{
|
||||||
List<Value> items = getItems();
|
List<Value> items = getItems();
|
||||||
int size = items.size();
|
int size = items.size();
|
||||||
if (to < 0 || to > size) to = size;
|
int from = normalizeIndex(fromDesc, size);
|
||||||
if (from < 0 || from > size) from = size;
|
int to = normalizeIndex(toDesc, size);
|
||||||
if (from > to)
|
if (from > to)
|
||||||
return ListValue.of();
|
return ListValue.of();
|
||||||
return new ListValue((Collection<? extends Value>) getItems().subList((int)from, (int) to));
|
return new ListValue((Collection<? extends Value>) getItems().subList(from, to));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -395,10 +390,8 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
return false;
|
return false;
|
||||||
int index = (int)((NumericValue) ind).getLong();
|
int index = (int)((NumericValue) ind).getLong();
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{// only for values < 0
|
||||||
long range = abs(index) / numitems;
|
index = normalizeIndex(index, numitems);
|
||||||
index += (range + 2) * numitems;
|
|
||||||
index = index % numitems;
|
|
||||||
}
|
}
|
||||||
if (replace)
|
if (replace)
|
||||||
{
|
{
|
||||||
@@ -424,11 +417,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
public Value get(Value value)
|
public Value get(Value value)
|
||||||
{
|
{
|
||||||
long index = NumericValue.asNumber(value, "'address' to a list index").getLong();
|
long index = NumericValue.asNumber(value, "'address' to a list index").getLong();
|
||||||
int numitems = items.size();
|
return items.get(normalizeIndex(index, items.size()));
|
||||||
long range = abs(index)/numitems;
|
|
||||||
index += (range+2)*numitems;
|
|
||||||
index = index % numitems;
|
|
||||||
return items.get((int)index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -443,11 +432,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
{
|
{
|
||||||
if (!(where instanceof NumericValue) || items.isEmpty()) return false;
|
if (!(where instanceof NumericValue) || items.isEmpty()) return false;
|
||||||
long index = ((NumericValue) where).getLong();
|
long index = ((NumericValue) where).getLong();
|
||||||
int numitems = items.size();
|
items.remove(normalizeIndex(index, items.size()));
|
||||||
long range = abs(index)/numitems;
|
|
||||||
index += (range+2)*numitems;
|
|
||||||
index = index % numitems;
|
|
||||||
items.remove((int)index);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import net.minecraft.nbt.Tag;
|
|||||||
|
|
||||||
public class StringValue extends Value
|
public class StringValue extends Value
|
||||||
{
|
{
|
||||||
|
public static Value EMPTY = StringValue.of("");
|
||||||
|
|
||||||
private String str;
|
private String str;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -178,16 +178,14 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
|||||||
return getString().length();
|
return getString().length();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value slice(long from, long to)
|
public Value slice(long fromDesc, long toDesc)
|
||||||
{
|
{
|
||||||
String value = this.getString();
|
String value = this.getString();
|
||||||
int size = value.length();
|
int size = value.length();
|
||||||
if (to > size) to = -1;
|
int from = ListValue.normalizeIndex(fromDesc, size);
|
||||||
if (from < 0) from = 0;
|
int to = ListValue.normalizeIndex(toDesc, size);
|
||||||
if (from > size) from = size;
|
if (from > to) return StringValue.EMPTY;
|
||||||
if (to>=0)
|
return new StringValue(value.substring(from, to));
|
||||||
return new StringValue(value.substring((int)from, (int)to));
|
|
||||||
return new StringValue(value.substring((int)from));
|
|
||||||
}
|
}
|
||||||
public double readDoubleNumber()
|
public double readDoubleNumber()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user