004b72a86c7fad684be7821df3123c68c573c548
kent
  Mon Dec 23 15:50:56 2013 -0800
Adding slListRandomReduce and slListRandomSample for making samples of larger lists.
diff --git src/lib/obscure.c src/lib/obscure.c
index feaa622..990211a 100644
--- src/lib/obscure.c
+++ src/lib/obscure.c
@@ -667,30 +667,72 @@
         array[i] = el;
     for (i=0; i<4; ++i)
         shuffleArrayOfPointers(array, count);
     list = NULL;
     for (i=0; i<count; ++i)
         {
         array[i]->next = list;
         list = array[i];
         }
     freeMem(array);
     slReverse(&list);
     *pL = list;       
     }
 }
 
+void *slListRandomReduce(void *list, double reduceRatio)
+/* Reduce list to approximately reduceRatio times original size. Destroys original list. */
+{
+if (reduceRatio >= 1.0)
+    return list;
+int threshold = RAND_MAX * reduceRatio;
+struct slList *newList = NULL, *next, *el;
+for (el = list; el != NULL; el = next)
+    {
+    next = el->next;
+    if (rand() <= threshold)
+        {
+	slAddHead(&newList, el);
+	}
+    }
+return newList;
+}
+
+void *slListRandomSample(void *list, int maxCount)
+/* Return a sublist of list with at most maxCount. Destroy list in process */
+{
+if (list == NULL)
+    return list;
+int initialCount = slCount(list);
+if (initialCount <= maxCount)
+    return list;
+double reduceRatio = (double)maxCount/initialCount;
+if (reduceRatio < 0.9)
+    {
+    double conservativeReduceRatio = reduceRatio * 1.05;
+    list = slListRandomReduce(list, conservativeReduceRatio);
+    }
+int midCount = slCount(list);
+if (midCount <= maxCount)
+    return list;
+shuffleList(list);
+struct slList *lastEl = slElementFromIx(list, maxCount-1);
+lastEl->next = NULL;
+return list;
+}
+
+
 char *stripCommas(char *position)
 /* make a new string with commas stripped out */
 {
 char *newPos = cloneString(position);
 char *nPtr = newPos;
 
 if (position == NULL)
     return NULL;
 while((*nPtr = *position++))
     if (*nPtr != ',')
 	nPtr++;
 
 return newPos;
 }