001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.util.filter;
031
032import java.util.ArrayList;
033import java.util.Collection;
034import java.util.Iterator;
035
036import org.openimaj.util.array.ArrayIterator;
037import org.openimaj.util.function.Predicate;
038
039/**
040 * Utilities for filtering collections by applying a {@link Predicate}.
041 * 
042 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
043 */
044public class FilterUtils {
045        private FilterUtils() {
046        }
047
048        /**
049         * Filter a collection, returning the accepted items in an {@link ArrayList}
050         * .
051         * 
052         * @see Predicate#test(Object)
053         * 
054         * @param <T>
055         *            type of object being filtered
056         * @param <Q>
057         *            type of object accepted by the filter
058         * @param in
059         *            input collection
060         * @param filter
061         *            the filter
062         * @return the list of accepted items
063         */
064        public static <T, Q extends T> ArrayList<Q> filter(final Collection<Q> in, final Predicate<T> filter) {
065                final ArrayList<Q> out = new ArrayList<Q>();
066
067                for (final Q item : in)
068                        if (filter.test(item))
069                                out.add(item);
070
071                return out;
072        }
073
074        /**
075         * Filter a collection, storing the accepted items in the given output
076         * collection.
077         * 
078         * @see Predicate#test(Object)
079         * 
080         * @param <T>
081         *            type of object being filtered
082         * @param in
083         *            input collection
084         * @param out
085         *            output collection
086         * @param filter
087         *            the filter
088         * @return the list of accepted items
089         */
090        public static <T> Collection<T> filter(final Collection<? extends T> in, final Collection<T> out,
091                        final Predicate<T> filter)
092        {
093                for (final T item : in)
094                        if (filter.test(item))
095                                out.add(item);
096
097                return out;
098        }
099
100        /**
101         * Create an iterator that filters items from the given {@link Iterable}.
102         * 
103         * @see Predicate#test(Object)
104         * 
105         * @param <T>
106         *            type of object being filtered
107         * @param iterable
108         *            {@link Iterable} to filter
109         * @param filter
110         *            the filter
111         * @return the list of accepted items
112         */
113        public static <T> Iterator<T> filteredIterator(final Iterable<? extends T> iterable, final Predicate<T> filter) {
114                return filteredIterator(iterable.iterator(), filter);
115        }
116
117        /**
118         * Create an iterator that filters items from the given {@link Iterator}.
119         * 
120         * @see Predicate#test(Object)
121         * 
122         * @param <T>
123         *            type of object being filtered
124         * @param iterator
125         *            {@link Iterator} to filter
126         * @param filter
127         *            the filter
128         * @return the list of accepted items
129         */
130        public static <T> Iterator<T> filteredIterator(final Iterator<? extends T> iterator, final Predicate<T> filter) {
131                return new Iterator<T>() {
132                        T next;
133
134                        @Override
135                        public boolean hasNext() {
136                                if (next != null)
137                                        return true;
138
139                                if (!iterator.hasNext())
140                                        return false;
141
142                                while (iterator.hasNext()) {
143                                        next = iterator.next();
144
145                                        if (filter.test(next))
146                                                return true;
147                                }
148
149                                return false;
150                        }
151
152                        @Override
153                        public T next() {
154                                if (next == null)
155                                        hasNext();
156
157                                final T ret = next;
158                                next = null;
159                                return ret;
160                        }
161
162                        @Override
163                        public void remove() {
164                                iterator.remove();
165                        }
166                };
167        }
168
169        /**
170         * Create an iterator that filters items from the given array.
171         * 
172         * @see Predicate#test(Object)
173         * 
174         * @param <T>
175         *            type of object being filtered
176         * @param array
177         *            to filter
178         * @param filter
179         *            the filter
180         * @return the list of accepted items
181         */
182        public static <T> Iterator<T> filteredIterator(final T[] array, final Predicate<T> filter) {
183                return filteredIterator(new ArrayIterator<T>(array), filter);
184        }
185}