/*
* Copyright (C) 2015 Information Retrieval Group at Universidad Autónoma
* de Madrid, http://ir.ii.uam.es
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package es.uam.eps.ir.ranksys.fast.feature;
import es.uam.eps.ir.ranksys.fast.index.FastFeatureIndex;
import es.uam.eps.ir.ranksys.fast.index.FastItemIndex;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.jooq.lambda.tuple.Tuple3;
import org.ranksys.core.util.tuples.Tuple2io;
import static org.ranksys.core.util.tuples.Tuples.tuple;
/**
* Simple implementation of FastFeatureData backed by nested lists.
*
* @author Saúl Vargas (saul.vargas@uam.es)
*
* @param <I> type of the items
* @param <F> type of the features
* @param <V> type of the information about item-feature pairs
*/
public class SimpleFastFeatureData<I, F, V> extends AbstractFastFeatureData<I, F, V> {
private final List<List<Tuple2io<V>>> iidxList;
private final List<List<Tuple2io<V>>> fidxList;
/**
* Constructor.
*
* @param iidxList list of lists of item-feature pairs by item index
* @param fidxList list of lists of item-feature pairs by feature index
* @param ii item index
* @param fi feature index
*/
protected SimpleFastFeatureData(List<List<Tuple2io<V>>> iidxList, List<List<Tuple2io<V>>> fidxList, FastItemIndex<I> ii, FastFeatureIndex<F> fi) {
super(ii, fi);
this.iidxList = iidxList;
this.fidxList = fidxList;
}
@Override
public Stream<Tuple2io<V>> getIidxFeatures(int iidx) {
if (iidxList.get(iidx) == null) {
return Stream.empty();
}
return iidxList.get(iidx).stream();
}
@Override
public Stream<Tuple2io<V>> getFidxItems(int fidx) {
if (fidxList.get(fidx) == null) {
return Stream.empty();
}
return fidxList.get(fidx).stream();
}
@Override
public int numItems(int fidx) {
if (fidxList.get(fidx) == null) {
return 0;
}
return fidxList.get(fidx).size();
}
@Override
public int numFeatures(int iidx) {
if (iidxList.get(iidx) == null) {
return 0;
}
return iidxList.get(iidx).size();
}
@Override
public IntStream getIidxWithFeatures() {
return IntStream.range(0, numItems())
.filter(iidx -> iidxList.get(iidx) != null);
}
@Override
public IntStream getFidxWithItems() {
return IntStream.range(0, numFeatures())
.filter(fidx -> fidxList.get(fidx) != null);
}
@Override
public int numItemsWithFeatures() {
return (int) iidxList.stream()
.filter(Objects::nonNull).count();
}
@Override
public int numFeaturesWithItems() {
return (int) fidxList.stream()
.filter(Objects::nonNull).count();
}
/**
* Loads a SimpleFastFeatureData by processing a stream of item-feature-value triples.
*
* @param <I> type of items
* @param <F> type of feats
* @param <V> type of value
* @param tuples item-feature-value triples
* @param iIndex item index
* @param fIndex feat index
* @return a SimpleFastFeatureData containing the information from the input triples
*/
public static <I, F, V> SimpleFastFeatureData<I, F, V> load(Stream<Tuple3<I, F, V>> tuples, FastItemIndex<I> iIndex, FastFeatureIndex<F> fIndex) {
List<List<Tuple2io<V>>> iidxList = new ArrayList<>();
for (int iidx = 0; iidx < iIndex.numItems(); iidx++) {
iidxList.add(null);
}
List<List<Tuple2io<V>>> fidxList = new ArrayList<>();
for (int fidx = 0; fidx < fIndex.numFeatures(); fidx++) {
fidxList.add(null);
}
tuples.forEach(t -> {
int iidx = iIndex.item2iidx(t.v1);
int fidx = fIndex.feature2fidx(t.v2);
if (iidx == -1 || fidx == -1) {
return;
}
List<Tuple2io<V>> iList = iidxList.get(iidx);
if (iList == null) {
iList = new ArrayList<>();
iidxList.set(iidx, iList);
}
iList.add(tuple(fidx, t.v3));
List<Tuple2io<V>> fList = fidxList.get(fidx);
if (fList == null) {
fList = new ArrayList<>();
fidxList.set(fidx, fList);
}
fList.add(tuple(iidx, t.v3));
});
return new SimpleFastFeatureData<>(iidxList, fidxList, iIndex, fIndex);
}
}