All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eolang.EOarray Maven / Gradle / Ivy

The newest version!
package org.eolang;

import org.eolang.core.EOObject;
import org.paukov.combinatorics3.Generator;

import java.util.List;
import java.util.Objects;

/**
 * Represents an array data structure.
 */
public class EOarray extends EOObject {

    /**
     * The underlying data structure behind this array is a Java List.
     * Effectively, the {@code _array} is an unmodifiable list since both
     * constructors of this class rely on the {@code List.of()} method.
     */
    private final List _array;

    /**
     * Instantiates an empty array.
     */
    public EOarray() {
        _array = List.of();
    }

    /**
     * Instantiates a non-empty array.
     *
     * @param objects contents of the array being instantiated.
     */
    public EOarray(EOObject... objects) {
        _array = List.of(objects);
    }

    /**
     * Appends {@code obj} to the end of this array.
     * 

* This operation does not mutate the original array. * Instead, it produces a copy of this array and appends {@code obj} to the end of it. * * @return a copy of this array with {@code obj} appended as its last element. */ public EOarray EOappend(EOObject obj) { EOObject[] newArray = new EOObject[_array.size() + 1]; System.arraycopy(_array.toArray(), 0, newArray, 0, _array.size()); newArray[_array.size()] = obj; return new EOarray(newArray); } /** * If {@code obj} is an EOarray appends item of {@code obj} to to the end of this array. * Otherwise appends {@code obj} to the end of this array. *

* This operation does not mutate the original array. * Instead, it produces a copy of this array and appends {@code obj} to the end of it. * * @return a copy of this array with {@code obj} appended as its last element. */ public EOarray EOappendAll(EOObject obj) { try { int array2Size = obj._getAttribute("EOlength")._getData().toInt().intValue(); if (array2Size > 0) { EOObject[] newArray; newArray = new EOObject[_array.size() + array2Size]; System.arraycopy(_array.toArray(), 0, newArray, 0, _array.size()); for (int i = _array.size(); i < newArray.length; ++i) { newArray[i] = obj._getAttribute("EOget", new EOint(i - _array.size())); } return new EOarray(newArray); } return this; } catch (Exception e) { return EOappend(obj); } } /** * Evaluates {@code evaluatorObject} against each element of this array. Results of evaluations are not considered. * This method always returns {@code true}. Basically, this method is useful to dataize (in other words, execute or * evaluate) some routine against each element of an array when results are not needed. * * @param evaluatorObject an EO object that must have an {@code each} attribute which must have a free attribute * that receives the current element being utilized by {@code evaluatorObject}. * The name of the free attribute does not matter and may be chosen freely. * The {@code each} attribute must bind an expression to be evaluated to {@code @}. * @return {@code true}. */ public EObool EOeach(EOObject evaluatorObject) { for (EOObject current : _array) { evaluatorObject._getAttribute("EOeach", current)._getData(); } return new EObool(true); } /** * Retrieves the element at the position {@code i} of this array. * * @param i an index of the element to be fetched. * @return an element at the position {@code i}. * @throws IndexOutOfBoundsException if {@code i} is out of bounds of this array * (i.e., {@code array.length <= i < 0}). */ public EOObject EOget(EOObject i) { int position = i._getData().toInt().intValue(); if (position >= _array.size() || position < 0) { throw new IndexOutOfBoundsException( String.format( "Cannot retrieve the element at the position %d of the following array: %s. The index is out of bounds.", position, this ) ); } return _array.get(position); } /** * Determines if this array is empty. * * @return {@code true} if this array is empty, otherwise {@code false}. */ public EObool EOisEmpty() { return new EObool(_array.isEmpty()); } /** * Retrieves the length of this array. * * @return an {@code int} representing the length of this array. */ public EOint EOlength() { return new EOint(_array.size()); } /** * Transforms this array in accordance with {@code mapperObject}. *

* This operation does not mutate the original array. * Instead, it produces a copy of this array where each element is transformed with {@code mapperObject}. * * @param mapperObject an EO object that must have a {@code map} attribute which must have a free attribute * that receives the current element being transformed. * The name of the free attribute does not matter and may be chosen freely. * The {@code map} attribute must bind a transformation * technique (function) to its {@code @} attribute. * @return an {@code array} object containing mapped elements. */ public EOarray EOmap(EOObject mapperObject) { int length = _array.size(); EOObject[] mappedArray = new EOObject[length]; for (int i = 0; i < length; i++) { mappedArray[i] = mapperObject._getAttribute("EOmap", _array.get(i))._getDecoratedObject(); } return new EOarray(mappedArray); } /** * Transforms this array in accordance with {@code mapperObject}. * This variant of mapping considers indices while transforming elements. *

* This operation does not mutate the original array. * Instead, it produces a copy of this array where each element is transformed with {@code mapperObject}. * * @param mapperObject an EO object that must have a {@code mapi} attribute which must have two free attributes: * 1. The first free attribute receives the current element being transformed. * 2. The second free attribute receives the index of the current element being transformed. * The order of the free attributes matters, and their names do not. * The {@code mapi} attribute must bind a transformation * technique (function) to its {@code @} attribute. * @return an {@code array} object containing mapped elements. */ public EOarray EOmapi(EOObject mapperObject) { int length = _array.size(); EOObject[] mappedArray = new EOObject[length]; for (int i = 0; i < length; i++) { mappedArray[i] = mapperObject._getAttribute("EOmapi", _array.get(i), new EOint(i))._getDecoratedObject(); } return new EOarray(mappedArray); } /** * Retrieves all pairs of the elements of this array. * Resulting pairs are essentially 2-combinations with no repetitions (order is not taken into account). * Uniqueness of elements within pairs is not guaranteed (this method, however, guarantees that resulting pairs * themselves are unique regarding positions of included elements), so users of this method should consider * eliminating duplicates before retrieving pairs if unique elements within pairs are required (see examples below). *

* Example #1: * array([1, 2, 3]).pairs -> array([tuple(1, 2), tuple(1, 3), tuple(2, 3)]) * Example #2: * array([1, 2, 2]).pairs -> array([tuple(1, 2), tuple(1, 2), tuple(2, 2)]) * * @return an {@code array} of {@code tuple} objects with pairs of the elements of this array. */ public EOarray EOpairs() { return new EOarray( Generator.combination(this._array.toArray(EOObject[]::new)) .simple(2) .stream() .map(pair -> new EOtuple(pair.get(0), pair.get(1))) .toArray(EOObject[]::new) ); } /** * Performs the operation of reduction of this array * (i.e., this method transforms this array into a single value in accordance with {@code reducerObject}). * * @param accumulator an initial value of the accumulator. * @param reducerObject an EO object that must have a {@code reduce} attribute which must have two free attributes: * 1. The first free attribute receives the current value of the accumulator. * 2. The second free attribute receives the current element being operated over. * The order of the free attributes matters, and their names do not. * The {@code reduce} attribute must bind a reduction technique (function) to {@code @}. * @return the value of the accumulator after operating over the last element of this array (i.e., the result of reduction). */ public EOObject EOreduce(EOObject accumulator, EOObject reducerObject) { EOObject out = accumulator; for (EOObject eoObject : _array) { out = reducerObject._getAttribute("EOreduce", out, eoObject)._getDecoratedObject(); } return out; } /** * Performs the operation of reduction of this array * (i.e., this method transforms this array into a single value in accordance with {@code reducerObject}). * This variant of reduction considers indices while operating over elements. * * @param accumulator an initial value of the accumulator. * @param reducerObject an EO object that must have a {@code reducei} attribute which must have three free attributes: * 1. The first free attribute receives the current value of the accumulator. * 2. The second free attribute receives the current element being operated over. * 3. The third free attribute receives the index of the current element. * The order of the free attributes matters, and their names do not. * The {@code reducei} attribute must bind a reduction technique (function) to {@code @}. * @return the value of the accumulator after operating over the last element of this array (i.e., the result of reduction). */ public EOObject EOreducei(EOObject accumulator, EOObject reducerObject) { EOObject out = accumulator; int length = _array.size(); for (int i = 0; i < length; i++) { out = reducerObject._getAttribute("EOreducei", out, _array.get(i), new EOint(i))._getDecoratedObject(); } return out; } /** * !!!For testing purposes only!!! *

* Determines if this array is equal to the {@code o} object. * To do it, this method checks that the {@code o} object is an array * and it contains similar elements by delegating equality checks to * the elements themselves. *

* This method can be called only in the testing environment * since all methods within the EO environment have the 'EO' prefix. */ @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; EOarray eOarray = (EOarray) o; return _array.equals(eOarray._array); } @Override public int hashCode() { return Objects.hash(_array); } /** * !!!For testing purposes only!!! *

* Produces a string that represents this array. * The resulting string has the following form: * array([elem1, elem2, elem3, elem4]), * where each elemN is converted to a string, too. *

* Example: * Say, an array has three int elements: 1, 2, 3. * Then, the string representation of the array is: * array([int(1), int(2), int(3)]). *

* This method can be called only in the testing environment * since all methods within the EO environment have the 'EO' prefix. */ @Override public String toString() { final StringBuilder sb = new StringBuilder("array(["); for (EOObject o : _array) { sb.append(o.toString()).append(", "); } if (_array.size() > 0) { sb.delete(sb.length() - 2, sb.length()); } sb.append("])"); return sb.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy