Index: trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 5577)
+++ trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 5578)
@@ -433,7 +433,9 @@
                 , GBC.eol());
             right.add(new SearchKeywordRow(hcbSearchString)
-                .addTitle(tr("relations"))
+                .addTitle(tr("related objects"))
                 .addKeyword("child <i>expr</i>", "child ", tr("all children of objects matching the expression"), "child building")
                 .addKeyword("parent <i>expr</i>", "parent ", tr("all parents of objects matching the expression"), "parent bus_stop")
+                .addKeyword("nth:<i>7</i>", "nth: ", tr("n-th member of relation and/or n-th node of way"), "nth:5 (child type:relation)")
+                .addKeyword("nth%:<i>7</i>", "nth: ", tr("every n-th member of relation and/or every n-th node of way"), "nth%:100 (child waterway)")
                 , GBC.eol());
             right.add(new SearchKeywordRow(hcbSearchString)
Index: trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 5577)
+++ trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 5578)
@@ -101,5 +101,5 @@
                 "changeset", "nodes", "tags", "areasize", "modified", "selected",
                 "incomplete", "untagged", "closed", "new", "indownloadarea",
-                "allindownloadarea", "inview", "allinview", "timestamp");
+                "allindownloadarea", "inview", "allinview", "timestamp", "nth", "nth%");
 
         @Override
@@ -138,4 +138,8 @@
                 else if ("areasize".equals(keyword))
                     return new AreaSize(tokenizer);
+                else if ("nth".equals(keyword))
+                    return new Nth(tokenizer, false);
+                else if ("nth%".equals(keyword))
+                    return new Nth(tokenizer, true);
                 else if ("timestamp".equals(keyword)) {
                     String rangeS = " " + tokenizer.readTextOrNumber() + " "; // add leading/trailing space in order to get expected split (e.g. "a--" => {"a", ""})
@@ -785,4 +789,42 @@
         @Override public String toString() {
             return "role=" + role;
+        }
+    }
+
+    /**
+     * Matches the n-th object of a relation and/or the n-th node of a way.
+     */
+    private static class Nth extends Match {
+
+        private final int nth;
+        private final boolean modulo;
+
+        public Nth(PushbackTokenizer tokenizer, boolean modulo) throws ParseError {
+            this((int) tokenizer.readNumber(tr("Primitive id expected")), modulo);
+        }
+
+        private Nth(int nth, boolean modulo) {
+            this.nth = nth;
+            this.modulo = modulo;
+        }
+
+        @Override
+        public boolean match(OsmPrimitive osm) {
+            for (OsmPrimitive p : osm.getReferrers()) {
+                Integer idx = null;
+                if (p instanceof Way) {
+                    Way w = (Way) p;
+                    idx = w.getNodes().indexOf(osm);
+                } else if (p instanceof Relation) {
+                    Relation r = (Relation) p;
+                    idx = r.getMemberPrimitivesList().indexOf(osm);
+                }
+                if (idx != null) {
+                    if (idx.intValue() == nth || (modulo && idx.intValue() % nth == 0)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
         }
     }
Index: trunk/src/org/openstreetmap/josm/data/osm/Relation.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 5577)
+++ trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 5578)
@@ -13,4 +13,5 @@
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
 import org.openstreetmap.josm.tools.CopyList;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -395,4 +396,13 @@
     }
 
+    public List<OsmPrimitive> getMemberPrimitivesList() {
+        return Utils.transform(getMembers(), new Utils.Function<RelationMember, OsmPrimitive>() {
+            @Override
+            public OsmPrimitive apply(RelationMember x) {
+                return x.getMember();
+            }
+        });
+    }
+
     @Override
     public OsmPrimitiveType getType() {
Index: trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 5577)
+++ trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 5578)
@@ -19,4 +19,6 @@
 import java.security.NoSuchAlgorithmException;
 import java.text.MessageFormat;
+import java.util.AbstractCollection;
+import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -455,34 +457,9 @@
      */
     public static <A, B> Collection<B> transform(final Collection<? extends A> c, final Function<A, B> f) {
-        return new Collection<B>() {
+        return new AbstractCollection<B>() {
 
             @Override
             public int size() {
                 return c.size();
-            }
-
-            @Override
-            public boolean isEmpty() {
-                return c.isEmpty();
-            }
-
-            @Override
-            public boolean contains(Object o) {
-                return c.contains(o);
-            }
-
-            @Override
-            public Object[] toArray() {
-                return c.toArray();
-            }
-
-            @Override
-            public <T> T[] toArray(T[] a) {
-                return c.toArray(a);
-            }
-
-            @Override
-            public String toString() {
-                return c.toString();
             }
 
@@ -509,39 +486,31 @@
                 };
             }
+        };
+    }
+
+    /**
+     * Transforms the list {@code l} into an unmodifiable list and
+     * applies the {@link Function} {@code f} on each element upon access.
+     * @param <A> class of input collection
+     * @param <B> class of transformed collection
+     * @param l a collection
+     * @param f a function that transforms objects of {@code A} to objects of {@code B}
+     * @return the transformed unmodifiable list
+     */
+    public static <A, B> List<B> transform(final List<? extends A> l, final Function<A, B> f) {
+        return new AbstractList<B>() {
+
 
             @Override
-            public boolean add(B e) {
-                throw new UnsupportedOperationException();
+            public int size() {
+                return l.size();
             }
 
             @Override
-            public boolean remove(Object o) {
-                throw new UnsupportedOperationException();
-            }
-
-            @Override
-            public boolean containsAll(Collection<?> c) {
-                throw new UnsupportedOperationException();
-            }
-
-            @Override
-            public boolean addAll(Collection<? extends B> c) {
-                throw new UnsupportedOperationException();
-            }
-
-            @Override
-            public boolean removeAll(Collection<?> c) {
-                throw new UnsupportedOperationException();
-            }
-
-            @Override
-            public boolean retainAll(Collection<?> c) {
-                throw new UnsupportedOperationException();
-            }
-
-            @Override
-            public void clear() {
-                throw new UnsupportedOperationException();
-            }
+            public B get(int index) {
+                return f.apply(l.get(index));
+            }
+
+
         };
     }
