From 66be01eb29b4b823a2529773946d9bd423c23043 Mon Sep 17 00:00:00 2001 From: shaper Date: Fri, 6 Sep 2002 02:12:26 +0000 Subject: [PATCH] Added various variants of splice() to facilitate array manipulations by those who are accustomed to slinging backticks and slurping files with Perl. Someday perhaps we'll go whole-hog and implement more of the Perl-style splicing antics (allowing negative offset and/or length, and optionally passing a list of items to splice into the array.) git-svn-id: https://samskivert.googlecode.com/svn/trunk@827 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- .../java/com/samskivert/util/ArrayUtil.java | 210 +++++++++++++++++- .../com/samskivert/util/ArrayUtilTest.java | 82 +++++-- 2 files changed, 275 insertions(+), 17 deletions(-) diff --git a/projects/samskivert/src/java/com/samskivert/util/ArrayUtil.java b/projects/samskivert/src/java/com/samskivert/util/ArrayUtil.java index dd609ac0..57dc421d 100644 --- a/projects/samskivert/src/java/com/samskivert/util/ArrayUtil.java +++ b/projects/samskivert/src/java/com/samskivert/util/ArrayUtil.java @@ -1,5 +1,5 @@ // -// $Id: ArrayUtil.java,v 1.14 2002/08/19 23:22:09 shaper Exp $ +// $Id: ArrayUtil.java,v 1.15 2002/09/06 02:12:25 shaper Exp $ // // samskivert library - useful routines for java programs // Copyright (C) 2001 Walter Korman @@ -313,6 +313,214 @@ public class ArrayUtil return -(low + 1); // key not found. } + /** + * Creates and returns a new array sized to fit and populated with the + * subset of values from indexes 0 to offset - + * 1 (inclusive) in the supplied array. + * + * @param values the array of values to splice. + * @param offset the index within the values array after + * which all subsequent values are to be removed. This must be a + * valid index within the values array. + */ + public static byte[] splice (byte[] values, int offset) + { + return splice(values, offset, values.length - offset); + } + + /** + * Creates and returns a new array sized to fit and populated with the + * concatenated subset of values from indexes 0 to + * offset - 1, and offset + length to + * values.length (inclusive) in the supplied array. + * + * @param values the array of values to splice. + * @param offset the index within the values array at + * which the first element will be removed. This must be a valid + * index within the values array. + * @param length the number of elements to be removed. Note that + * offset + length must be a valid index within the + * values array. + */ + public static byte[] splice (byte[] values, int offset, int length) + { + // make sure we've something to work with + if (values == null) { + throw new IllegalArgumentException("Can't splice a null array."); + } + + // require that the entire range to remove be within the array bounds + int size = values.length; + int tstart = offset + length; + if (offset < 0 || tstart > size) { + throw new ArrayIndexOutOfBoundsException( + "Splice range out of bounds [offset=" + offset + + ", length=" + length + ", size=" + size + "]."); + } + + // create a new array and populate it with the spliced-in values + byte[] nvalues = new byte[size - length]; + System.arraycopy(values, 0, nvalues, 0, offset); + System.arraycopy(values, tstart, nvalues, offset, size - tstart); + return nvalues; + } + + /** + * Creates and returns a new array sized to fit and populated with the + * subset of values from indexes 0 to offset - + * 1 (inclusive) in the supplied array. + * + * @param values the array of values to splice. + * @param offset the index within the values array after + * which all subsequent values are to be removed. This must be a + * valid index within the values array. + */ + public static int[] splice (int[] values, int offset) + { + return splice(values, offset, values.length - offset); + } + + /** + * Creates and returns a new array sized to fit and populated with the + * concatenated subset of values from indexes 0 to + * offset - 1, and offset + length to + * values.length (inclusive) in the supplied array. + * + * @param values the array of values to splice. + * @param offset the index within the values array at + * which the first element will be removed. This must be a valid + * index within the values array. + * @param length the number of elements to be removed. Note that + * offset + length must be a valid index within the + * values array. + */ + public static int[] splice (int[] values, int offset, int length) + { + // make sure we've something to work with + if (values == null) { + throw new IllegalArgumentException("Can't splice a null array."); + } + + // require that the entire range to remove be within the array bounds + int size = values.length; + int tstart = offset + length; + if (offset < 0 || tstart > size) { + throw new ArrayIndexOutOfBoundsException( + "Splice range out of bounds [offset=" + offset + + ", length=" + length + ", size=" + size + "]."); + } + + // create a new array and populate it with the spliced-in values + int[] nvalues = new int[size - length]; + System.arraycopy(values, 0, nvalues, 0, offset); + System.arraycopy(values, tstart, nvalues, offset, size - tstart); + return nvalues; + } + + /** + * Creates and returns a new array sized to fit and populated with the + * subset of values from indexes 0 to offset - + * 1 (inclusive) in the supplied array. + * + * @param values the array of values to splice. + * @param offset the index within the values array after + * which all subsequent values are to be removed. This must be a + * valid index within the values array. + */ + public static String[] splice (String[] values, int offset) + { + return splice(values, offset, values.length - offset); + } + + /** + * Creates and returns a new array sized to fit and populated with the + * concatenated subset of values from indexes 0 to + * offset - 1, and offset + length to + * values.length (inclusive) in the supplied array. + * + * @param values the array of values to splice. + * @param offset the index within the values array at + * which the first element will be removed. This must be a valid + * index within the values array. + * @param length the number of elements to be removed. Note that + * offset + length must be a valid index within the + * values array. + */ + public static String[] splice (String[] values, int offset, int length) + { + // make sure we've something to work with + if (values == null) { + throw new IllegalArgumentException("Can't splice a null array."); + } + + // require that the entire range to remove be within the array bounds + int size = values.length; + int tstart = offset + length; + if (offset < 0 || tstart > size) { + throw new ArrayIndexOutOfBoundsException( + "Splice range out of bounds [offset=" + offset + + ", length=" + length + ", size=" + size + "]."); + } + + // create a new array and populate it with the spliced-in values + String[] nvalues = new String[size - length]; + System.arraycopy(values, 0, nvalues, 0, offset); + System.arraycopy(values, tstart, nvalues, offset, size - tstart); + return nvalues; + } + + /** + * Creates and returns a new array sized to fit and populated with the + * subset of values from indexes 0 to offset - + * 1 (inclusive) in the supplied array. + * + * @param values the array of values to splice. + * @param offset the index within the values array after + * which all subsequent values are to be removed. This must be a + * valid index within the values array. + */ + public static Object[] splice (Object[] values, int offset) + { + return splice(values, offset, values.length - offset); + } + + /** + * Creates and returns a new array sized to fit and populated with the + * concatenated subset of values from indexes 0 to + * offset - 1, and offset + length to + * values.length (inclusive) in the supplied array. + * + * @param values the array of values to splice. + * @param offset the index within the values array at + * which the first element will be removed. This must be a valid + * index within the values array. + * @param length the number of elements to be removed. Note that + * offset + length must be a valid index within the + * values array. + */ + public static Object[] splice (Object[] values, int offset, int length) + { + // make sure we've something to work with + if (values == null) { + throw new IllegalArgumentException("Can't splice a null array."); + } + + // require that the entire range to remove be within the array bounds + int size = values.length; + int tstart = offset + length; + if (offset < 0 || tstart > size) { + throw new ArrayIndexOutOfBoundsException( + "Splice range out of bounds [offset=" + offset + + ", length=" + length + ", size=" + size + "]."); + } + + // create a new array and populate it with the spliced-in values + Object[] nvalues = new Object[size - length]; + System.arraycopy(values, 0, nvalues, 0, offset); + System.arraycopy(values, tstart, nvalues, offset, size - tstart); + return nvalues; + } + /** The random object used when shuffling an array. */ protected static Random _rnd = new Random(); } diff --git a/projects/samskivert/tests/src/java/com/samskivert/util/ArrayUtilTest.java b/projects/samskivert/tests/src/java/com/samskivert/util/ArrayUtilTest.java index fecf1b57..44e64c61 100644 --- a/projects/samskivert/tests/src/java/com/samskivert/util/ArrayUtilTest.java +++ b/projects/samskivert/tests/src/java/com/samskivert/util/ArrayUtilTest.java @@ -1,11 +1,13 @@ // -// $Id: ArrayUtilTest.java,v 1.1 2002/08/12 01:10:32 mdb Exp $ +// $Id: ArrayUtilTest.java,v 1.2 2002/09/06 02:12:26 shaper Exp $ package com.samskivert.util; import junit.framework.Test; import junit.framework.TestCase; +import com.samskivert.Log; + /** * Tests the {@link ArrayUtil} class. */ @@ -21,73 +23,121 @@ public class ArrayUtilTest extends TestCase // test reversing an array int[] values = new int[] { 0 }; int[] work = (int[])values.clone(); - reverse(work); + ArrayUtil.reverse(work); Log.info("reverse: " + StringUtil.toString(work)); values = new int[] { 0, 1, 2 }; work = (int[])values.clone(); - reverse(work); + ArrayUtil.reverse(work); Log.info("reverse: " + StringUtil.toString(work)); work = (int[])values.clone(); - reverse(work, 0, 2); + ArrayUtil.reverse(work, 0, 2); Log.info("reverse first-half: " + StringUtil.toString(work)); work = (int[])values.clone(); - reverse(work, 1, 2); + ArrayUtil.reverse(work, 1, 2); Log.info("reverse second-half: " + StringUtil.toString(work)); values = new int[] { 0, 1, 2, 3, 4 }; work = (int[])values.clone(); - reverse(work, 1, 3); + ArrayUtil.reverse(work, 1, 3); Log.info("reverse middle: " + StringUtil.toString(work)); values = new int[] { 0, 1, 2, 3 }; work = (int[])values.clone(); - reverse(work); + ArrayUtil.reverse(work); Log.info("reverse even: " + StringUtil.toString(work)); // test shuffling two elements values = new int[] { 0, 1 }; work = (int[])values.clone(); - shuffle(work, 0, 1); + ArrayUtil.shuffle(work, 0, 1); Log.info("first-half shuffle: " + StringUtil.toString(work)); work = (int[])values.clone(); - shuffle(work, 1, 1); + ArrayUtil.shuffle(work, 1, 1); Log.info("second-half shuffle: " + StringUtil.toString(work)); work = (int[])values.clone(); - shuffle(work); + ArrayUtil.shuffle(work); Log.info("full shuffle: " + StringUtil.toString(work)); // test shuffling three elements values = new int[] { 0, 1, 2 }; work = (int[])values.clone(); - shuffle(work, 0, 2); + ArrayUtil.shuffle(work, 0, 2); Log.info("first-half shuffle: " + StringUtil.toString(work)); work = (int[])values.clone(); - shuffle(work, 1, 2); + ArrayUtil.shuffle(work, 1, 2); Log.info("second-half shuffle: " + StringUtil.toString(work)); work = (int[])values.clone(); - shuffle(work); + ArrayUtil.shuffle(work); Log.info("full shuffle: " + StringUtil.toString(work)); // test shuffling ten elements values = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; work = (int[])values.clone(); - shuffle(work, 0, 5); + ArrayUtil.shuffle(work, 0, 5); Log.info("first-half shuffle: " + StringUtil.toString(work)); work = (int[])values.clone(); - shuffle(work, 5, 5); + ArrayUtil.shuffle(work, 5, 5); Log.info("second-half shuffle: " + StringUtil.toString(work)); work = (int[])values.clone(); - shuffle(work); + ArrayUtil.shuffle(work); Log.info("full shuffle: " + StringUtil.toString(work)); + + // test splicing with simple truncate beyond offset + values = new int[] { 0, 1, 2 }; + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 0); + Log.info("splice truncate 0: " + StringUtil.toString(work)); + + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 1); + Log.info("splice truncate 1: " + StringUtil.toString(work)); + + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 2); + Log.info("splice truncate 2: " + StringUtil.toString(work)); + + values = new int[] { 0 }; + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 0); + Log.info("single element splice truncate 0: " + + StringUtil.toString(work)); + + // test splicing out a single element + values = new int[] { 0, 1, 2 }; + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 0, 1); + Log.info("splice concat 0, 1: " + StringUtil.toString(work)); + + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 1, 1); + Log.info("splice concat 1, 1: " + StringUtil.toString(work)); + + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 2, 1); + Log.info("splice concat 2, 1: " + StringUtil.toString(work)); + + // test splicing out two elements + values = new int[] { 0, 1, 2, 3 }; + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 0, 2); + Log.info("splice concat 0, 2: " + StringUtil.toString(work)); + + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 1, 2); + Log.info("splice concat 1, 2: " + StringUtil.toString(work)); + + work = (int[])values.clone(); + work = ArrayUtil.splice(work, 2, 2); + Log.info("splice concat 2, 2: " + StringUtil.toString(work)); } public static Test suite ()