2015-05-09 12 views
5

Tôi chỉ đang thực hành RX Java và muốn lấy vị trí trong một mảng cho các mục phù hợp với bộ lọc. Tôi không thể nhìn thấy bất kỳ cách rõ ràng để làm điều đó. Tôi đã nhìn vào có thể nén một phạm vi và có thể lặp lại quan sát được hoặc một cái gì đó nhưng nó đã nhanh chóng nhận được cách chi tiết và phức tạp hơn cho các vòng lặp.Cách thanh lịch để lấy chỉ mục bộ lọc hoặc đầu tiên với RX Java

Trả lời

13

Đã từng là mapWithIndexzipWithIndex nhà khai thác ở RxJava, nhưng chúng đã bị xóa, xem here lý do.

Vì vậy, bạn phải viết một số soạn sẵn thư viện một lần:

class Indexed<T> { 
    final int index; 
    final T value; 
    public Indexed(T value, int index) { 
     this.index = index; 
     this.value = value; 
    } 
    @Override 
    public String toString() { 
     return index + ") " + value; 
    } 
} 

Iterable<Integer> naturals = IntStream.iterate(0, i -> i + 1)::iterator; 

Nhưng sau đó, bạn có thể lấy nó một cách hợp lý ngắn gọn:

Observable<String> obs = Observable.just("zero", "one", "two", "three"); 
obs.zipWith(naturals, (s, i) -> new Indexed<String>(s, i)) 
    .filter(e -> e.value.length() > 4) 
    .subscribe(System.out::println); 
+0

Bạn có thể sử dụng 'Observable.range (0, list.size()) 'thay vì' naturals' nếu bạn không có quyền truy cập vào java 8 stream. – Pedram

2

Không có một cách chính xác để làm điều này. Câu trả lời của Samuel có thể là một. Nó cũng phụ thuộc vào bức tranh lớn hơn về mảng bạn là gì và cách bạn cần xử lý các kết quả trong thuê bao.

Đây là một (java7) ví dụ nơi Observer phát ra một ArrayList<String>:

strings.map(new Func1<ArrayList<String>, ArrayList<Integer>>() { 
      @Override 
      public ArrayList<Integer> call(ArrayList<String> strings) { 
       ArrayList<Integer> list = new ArrayList<>(); 
       for(String string: strings){ 
        if(statement){ 
         list.add(strings.indexOf(string)); 
        } 
       } 
       return list; 
      } 
     }).subscribe(new Action1<ArrayList<Integer>>() { 
      @Override 
      public void call(ArrayList<Integer> integers) { 
       doSomethingWithThePositions(integers); 
      } 
     }); 

Và đây là một ví dụ nơi Observer phát ra một String mỗi lần từ ArrayList của bạn:

final ArrayList<String> strings1 = new ArrayList<>(); 
Observable.from(strings1) 
     .filter(new Func1<String, Boolean>() { 
      @Override 
      public Boolean call(String s) { 
       return !s.isEmpty(); 
      } 
     }) 
     .subscribe(new Action1<String>() { 
      @Override 
      public void call(String s) { 
       int i = strings1.indexOf(s); 
       doSomethingWithThePosition(i); 
      } 
     }); 
+0

vâng rằng ví dụ thứ hai không phải là xấu, đầu tiên là chính xác là tôi đã cố gắng để tránh, cũng là lớp học tùy chỉnh tuple sam đề cập. – schwiz

2

tôi như câu trả lời của Samuel. Tôi đã viết một thực hiện biến áp của công cụ của mình đó là Java 6/7 tuân thủ và sử dụng một chỉ số dài (tôi có dòng suối dài để đối phó với!).

Bạn gọi nó là như thế này:

 
Observable.just("a", "b").compose(MapWithIndex.<String>instance()); 

Dưới đây là các lớp (nguồn và đơn vị kiểm tra here):

 
package com.github.davidmoten.util; 

import java.util.Iterator; 

import rx.Observable; 
import rx.Observable.Transformer; 
import rx.functions.Func2; 

import com.github.davidmoten.util.MapWithIndex.Indexed; 

public final class MapWithIndex<T> implements Transformer<T, Indexed<T>> { 

    private static class Holder { 
     static final MapWithIndex<?> INSTANCE = new MapWithIndex<Object>(); 
    } 

    @SuppressWarnings("unchecked") 
    public static <T> MapWithIndex<T> instance() { 
     return (MapWithIndex<T>) Holder.INSTANCE; 
    } 

    @Override 
    public Observable<Indexed<T>> call(Observable<T> source) { 

     return source.zipWith(NaturalNumbers.instance(), new Func2<T, Long, Indexed<T>>() { 

      @Override 
      public Indexed<T> call(T t, Long n) { 
       return new Indexed<T>(t, n); 
      } 
     }); 
    } 

    public static class Indexed<T> { 
     private final long index; 
     private final T value; 

     public Indexed(T value, long index) { 
      this.index = index; 
      this.value = value; 
     } 

     @Override 
     public String toString() { 
      return index + "->" + value; 
     } 

     public long index() { 
      return index; 
     } 

     public T value() { 
      return value; 
     } 

    } 

    private static final class NaturalNumbers implements Iterable<Long> { 

     private static class Holder { 
      static final NaturalNumbers INSTANCE = new NaturalNumbers(); 
     } 

     static NaturalNumbers instance() { 
      return Holder.INSTANCE; 
     } 

     @Override 
     public Iterator<Long> iterator() { 
      return new Iterator<Long>() { 

       private long n = 0; 

       @Override 
       public boolean hasNext() { 
        return true; 
       } 

       @Override 
       public Long next() { 
        return n++; 
       } 

       @Override 
       public void remove() { 
        throw new RuntimeException("not supported"); 
       } 
      }; 
     } 

    } 

} 
+0

Cảm ơn bạn đã chia sẻ, tôi đã xem xét dự án git của bạn để tham khảo trong tương lai có thể hữu ích vào một ngày nào đó! – schwiz

Các vấn đề liên quan