mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Merge pull request #1171 from adrianVmariano/master
Negative indexing in list_set and list_insert
This commit is contained in:
commit
abf6f33185
3 changed files with 70 additions and 32 deletions
79
lists.scad
79
lists.scad
|
@ -377,7 +377,7 @@ function bselect(list,index) =
|
|||
// Description:
|
||||
// Generates a list of `n` copies of the given value `val`.
|
||||
// If the count `n` is given as a list of counts, then this creates a
|
||||
// multi-dimensional array, filled with `val`.
|
||||
// multi-dimensional array, filled with `val`. If `n` is negative, returns the empty list.
|
||||
// Arguments:
|
||||
// val = The value to repeat to make the list or array.
|
||||
// n = The number of copies to make of `val`. Can be a list to make an array of copies.
|
||||
|
@ -386,6 +386,7 @@ function bselect(list,index) =
|
|||
// b = repeat(8, [2,3]); // Returns [[8,8,8], [8,8,8]]
|
||||
// c = repeat(0, [2,2,3]); // Returns [[[0,0,0],[0,0,0]], [[0,0,0],[0,0,0]]]
|
||||
// d = repeat([1,2,3],3); // Returns [[1,2,3], [1,2,3], [1,2,3]]
|
||||
// e = repeat(4, -1); // Returns []
|
||||
function repeat(val, n, i=0) =
|
||||
is_num(n)? [for(j=[1:1:n]) val] :
|
||||
assert( is_list(n), "Invalid count number.")
|
||||
|
@ -633,7 +634,9 @@ function list_pad(list, minlen, fill) =
|
|||
// Description:
|
||||
// Takes the input list and returns a new list such that `list[indices[i]] = values[i]` for all of
|
||||
// the (index,value) pairs supplied and unchanged for other indices. If you supply `indices` that are
|
||||
// beyond the length of the list then the list is extended and filled in with the `dflt` value.
|
||||
// larger that the length of the list then the list is extended and filled in with the `dflt` value.
|
||||
// If you specify indices smaller than zero then they index from the end, with -1 being the last element.
|
||||
// Negative indexing does not wrap around: an error occurs if you give a value smaller than `-len(list)`.
|
||||
// If you set `minlen` then the list is lengthed, if necessary, by padding with `dflt` to that length.
|
||||
// Repetitions in `indices` are not allowed. The lists `indices` and `values` must have the same length.
|
||||
// If `indices` is given as a scalar, then that index of the given `list` will be set to the scalar value of `values`.
|
||||
|
@ -646,29 +649,45 @@ function list_pad(list, minlen, fill) =
|
|||
// Example:
|
||||
// a = list_set([2,3,4,5], 2, 21); // Returns: [2,3,21,5]
|
||||
// b = list_set([2,3,4,5], [1,3], [81,47]); // Returns: [2,81,4,47]
|
||||
function list_set(list=[],indices,values,dflt=0,minlen=0) =
|
||||
function list_set(list=[],indices,values,dflt=0,minlen=0) =
|
||||
assert(is_list(list))
|
||||
!is_list(indices)? (
|
||||
(is_finite(indices) && indices<len(list))
|
||||
? concat([for (i=idx(list)) i==indices? values : list[i]], repeat(dflt, minlen-len(list)))
|
||||
: list_set(list,[indices],[values],dflt)
|
||||
) :
|
||||
indices==[] && values==[]
|
||||
!is_list(indices)?
|
||||
assert(is_finite(indices))
|
||||
let(
|
||||
index = indices<0 ? indices+len(list) : indices
|
||||
)
|
||||
assert(index>=0, str("Index ",indices," is smaller than negative list length"))
|
||||
(
|
||||
index<len(list) ?
|
||||
[
|
||||
for(i=[0:1:index-1]) list[i],
|
||||
values,
|
||||
for(i=[index+1:1:len(list)-1]) list[i],
|
||||
for(i=[len(list):1:minlen-1]) dflt
|
||||
]
|
||||
: concat(list, repeat(dflt, index-len(list)), [values], repeat(dflt, minlen-index-1))
|
||||
)
|
||||
: indices==[] && values==[]
|
||||
? concat(list, repeat(dflt, minlen-len(list)))
|
||||
: assert(is_vector(indices) && is_list(values) && len(values)==len(indices),
|
||||
"Index list and value list must have the same length")
|
||||
let( midx = max(len(list)-1, max(indices)) )
|
||||
[
|
||||
for (i=[0:1:midx]) let(
|
||||
j = search(i,indices,0),
|
||||
k = j[0]
|
||||
)
|
||||
assert( len(j)<2, "Repeated indices are not allowed." )
|
||||
k!=undef
|
||||
? values[k]
|
||||
: i<len(list) ? list[i] : dflt,
|
||||
each repeat(dflt, minlen-max(len(list),max(indices)))
|
||||
];
|
||||
: assert(is_vector(indices) && is_list(values) && len(values)==len(indices),
|
||||
"Index list and value list must have the same length")
|
||||
let( indices = [for(ind=indices) ind<0 ? ind+len(list) : ind],
|
||||
midx = max(len(list)-1, max(indices))
|
||||
)
|
||||
assert(min(indices)>=0, "Index list contains value smaller than negative list length")
|
||||
[
|
||||
for (i=[0:1:midx])
|
||||
let(
|
||||
j = search(i,indices,0),
|
||||
k = j[0]
|
||||
)
|
||||
assert( len(j)<2, "Repeated indices are not allowed." )
|
||||
k!=undef ? values[k]
|
||||
: i<len(list) ? list[i]
|
||||
: dflt,
|
||||
each repeat(dflt, minlen-max(len(list),max(indices)+1))
|
||||
];
|
||||
|
||||
|
||||
|
||||
// Function: list_insert()
|
||||
|
@ -679,7 +698,9 @@ function list_set(list=[],indices,values,dflt=0,minlen=0) =
|
|||
// list = list_insert(list, indices, values);
|
||||
// Description:
|
||||
// Insert `values` into `list` before position `indices`. The indices for insertion
|
||||
// are based on the original list, before any insertions have occurred.
|
||||
// are based on the original list, before any insertions have occurred.
|
||||
// You can use negative indices to count from the end of the list. Note that -1 refers
|
||||
// to the last element, so the insertion will be *before* the last element.
|
||||
// Arguments:
|
||||
// list = list to insert items into
|
||||
// indices = index or list of indices where values are inserted
|
||||
|
@ -690,7 +711,9 @@ function list_set(list=[],indices,values,dflt=0,minlen=0) =
|
|||
function list_insert(list, indices, values) =
|
||||
assert(is_list(list))
|
||||
!is_list(indices) ?
|
||||
assert( is_finite(indices) && is_finite(values), "Invalid indices/values." )
|
||||
assert(is_finite(indices), "Invalid indices." )
|
||||
let(indices = indices<0 ? indices+len(list) : indices)
|
||||
assert(indices>=0, "Index is too small, must be >= len(list)")
|
||||
assert( indices<=len(list), "Indices must be <= len(list) ." )
|
||||
[
|
||||
for (i=idx(list)) each ( i==indices? [ values, list[i] ] : [ list[i] ] ),
|
||||
|
@ -701,9 +724,13 @@ function list_insert(list, indices, values) =
|
|||
"Index list and value list must have the same length")
|
||||
assert( max(indices)<=len(list), "Indices must be <= len(list)." )
|
||||
let(
|
||||
indices = [for(ind=indices) ind<0 ? ind+len(list) : ind],
|
||||
maxidx = max(indices),
|
||||
minidx = min(indices)
|
||||
) [
|
||||
)
|
||||
assert(minidx>=0, "Index list contains values that are too small")
|
||||
assert(maxidx<=len(list), "Index list contains values that are too large")
|
||||
[
|
||||
for (i=[0:1:minidx-1] ) list[i],
|
||||
for (i=[minidx : min(maxidx, len(list)-1)] )
|
||||
let(
|
||||
|
|
|
@ -365,7 +365,7 @@ include <structs.scad>
|
|||
// Example(2D,Med,NoAxes): Specifying by corner index. Use {{list_set()}} to construct the full chamfer cut list.
|
||||
// path = star(47, ir=25, or=50); // long path, lots of corners
|
||||
// chamfind = [8, 28, 60]; // But only want 3 chamfers
|
||||
// chamfcut = list_set([],chamfind,[10,13,15],minlen=len(path)-1);
|
||||
// chamfcut = list_set([],chamfind,[10,13,15],minlen=len(path));
|
||||
// rpath = round_corners(path, cut=chamfcut, method="chamfer");
|
||||
// polygon(rpath);
|
||||
// Example(2D,Med,NoAxes): Two-pass to chamfer and round by index. Use {{repeat_entries()}} to correct for first pass chamfers.
|
||||
|
@ -373,9 +373,9 @@ include <structs.scad>
|
|||
// path = star(47, ir=32, or=65); // long path, lots of corners
|
||||
// chamfind = [8, 28, 60]; // But only want 3 chamfers
|
||||
// roundind = [7,9,27,29,59,61]; // And 6 roundovers
|
||||
// chamfcut = list_set([],chamfind,[10,13,15],minlen=len(path)-1);
|
||||
// roundcut = list_set([],roundind,repeat(8,6),minlen=len(path)-1);
|
||||
// dups = list_set([], chamfind, repeat(2,len(chamfind)), dflt=1, minlen=len(path)-1);
|
||||
// chamfcut = list_set([],chamfind,[10,13,15],minlen=len(path));
|
||||
// roundcut = list_set([],roundind,repeat(8,6),minlen=len(path));
|
||||
// dups = list_set([], chamfind, repeat(2,len(chamfind)), dflt=1, minlen=len(path));
|
||||
// rpath1 = round_corners(path, cut=chamfcut, method="chamfer");
|
||||
// rpath2 = round_corners(rpath1, cut=repeat_entries(roundcut,dups));
|
||||
// polygon(rpath2);
|
||||
|
|
|
@ -160,7 +160,17 @@ module test_list_set() {
|
|||
assert_equal(list_set([1,2,3], 1, 4, dflt=12, minlen=5), [1,4,3,12,12]);
|
||||
assert_equal(list_set([1,2,3], [],[],dflt=12, minlen=5), [1,2,3,12,12]);
|
||||
assert_equal(list_set([1,2,3], 5,9), [1,2,3,0,0,9]);
|
||||
assert_equal(list_set([1,2,3], 5,9,dflt=12), [1,2,3,12,12,9]);
|
||||
assert_equal(list_set([1,2,3], 5,9,minlen=4), [1,2,3,0,0,9]);
|
||||
assert_equal(list_set([1,2,3], 5,9,minlen=7), [1,2,3,0,0,9,0]);
|
||||
assert_equal(list_set([1,2,3], 5,9,dflt=12), [1,2,3,12,12,9]);
|
||||
assert_equal(list_set([1,2,3], -1,12), [1,2,12]);
|
||||
assert_equal(list_set([1,2,3], -1,12,minlen=5), [1,2,12,0,0]);
|
||||
assert_equal(list_set([1,2,3], [-2,5], [8,9]), [1,8,3,0,0,9]);
|
||||
assert_equal(list_set([1,2,3], [-2,5], [8,9],minlen=8,dflt=-1), [1,8,3,-1,-1,9,-1,-1]);
|
||||
assert_equal(list_set([1,2,3], [-2,5], [8,9],minlen=3,dflt=-1), [1,8,3,-1,-1,9]);
|
||||
assert_equal(list_set([1,2,3], [0],[4], minlen=5), [4,2,3,0,0]);
|
||||
assert_equal(list_set([], 2,3), [0,0,3]);
|
||||
assert_equal(list_set([], 2,3,minlen=5,dflt=1), [1,1,3,1,1]);
|
||||
}
|
||||
test_list_set();
|
||||
|
||||
|
@ -201,7 +211,6 @@ module test_list_remove_values() {
|
|||
assert_equal(list_remove_values(test,99,all=true), test);
|
||||
assert_equal(list_remove_values(test,[99,100],all=true), test);
|
||||
assert_equal(list_remove_values(test,[99,100]), test);
|
||||
|
||||
}
|
||||
test_list_remove_values();
|
||||
|
||||
|
@ -213,6 +222,8 @@ module test_list_insert() {
|
|||
assert_equal(list_insert([3],[0,1], [1,2]), [1,3,2]);
|
||||
assert_equal(list_insert([1,2,3],[],[]),[1,2,3]);
|
||||
assert_equal(list_insert([], 0, 4),[4]);
|
||||
assert_equal(list_insert([1,2,3],-2,4), [1,4,2,3]);
|
||||
assert_equal(list_insert([1,2,3,4,5], [-1,-3],[12,9]), [1,2,9,3,4,12,5]);
|
||||
}
|
||||
test_list_insert();
|
||||
|
||||
|
|
Loading…
Reference in a new issue