The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<html><head><title>Statistics::WeightedSelection</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >

<style type="text/css">
 <!--/*--><![CDATA[/*><!--*/
BODY {
  background: white;
  color: black;
  font-family: arial,sans-serif;
  margin: 0;
  padding: 1ex;
}

A:link, A:visited {
  background: transparent;
  color: #006699;
}

A[href="#POD_ERRORS"] {
  background: transparent;
  color: #FF0000;
}

DIV {
  border-width: 0;
}

DT {
  margin-top: 1em;
  margin-left: 1em;
}

.pod { margin-right: 20ex; }

.pod PRE     {
  background: #eeeeee;
  border: 1px solid #888888;
  color: black;
  padding: 1em;
  white-space: pre;
}

.pod H1      {
  background: transparent;
  color: #006699;
  font-size: large;
}

.pod H1 A { text-decoration: none; }
.pod H2 A { text-decoration: none; }
.pod H3 A { text-decoration: none; }
.pod H4 A { text-decoration: none; }

.pod H2      {
  background: transparent;
  color: #006699;
  font-size: medium;
}

.pod H3      {
  background: transparent;
  color: #006699;
  font-size: medium;
  font-style: italic;
}

.pod H4      {
  background: transparent;
  color: #006699;
  font-size: medium;
  font-weight: normal;
}

.pod IMG     {
  vertical-align: top;
}

.pod .toc A  {
  text-decoration: none;
}

.pod .toc LI {
  line-height: 1.2em;
  list-style-type: none;
}

  /*]]>*/-->
</style>


</head>
<body class='pod'>
<!--
  generated by Pod::Simple::HTML v3.20,
  using Pod::Simple::PullParser v3.20,
  under Perl v5.016002 at Tue Jul  8 09:46:55 2014 GMT.

 If you want to change this HTML document, you probably shouldn't do that
   by changing it directly.  Instead, see about changing the calling options
   to Pod::Simple::HTML, and/or subclassing Pod::Simple::HTML,
   then reconverting this document from the Pod source.
   When in doubt, email the author of Pod::Simple::HTML for advice.
   See 'perldoc Pod::Simple::HTML' for more info.

-->

<!-- start doc -->
<a name='___top' class='dummyTopAnchor' ></a>

<div class='indexgroup'>
<ul   class='indexList indexList1'>
  <li class='indexItem indexItem1'><a href='#NAME'>NAME</a>
  <li class='indexItem indexItem1'><a href='#VERSION'>VERSION</a>
  <li class='indexItem indexItem1'><a href='#SYNOPSIS'>SYNOPSIS</a>
  <li class='indexItem indexItem1'><a href='#DESCRIPTION'>DESCRIPTION</a>
  <li class='indexItem indexItem1'><a href='#CAVEATS'>CAVEATS</a>
  <li class='indexItem indexItem1'><a href='#METHODS'>METHODS</a>
  <ul   class='indexList indexList2'>
    <li class='indexItem indexItem2'><a href='#CONSTRUCTOR_-_new()'>CONSTRUCTOR - new()</a>
    <li class='indexItem indexItem2'><a href='#add()'>add()</a>
    <li class='indexItem indexItem2'><a href='#get()'>get()</a>
    <li class='indexItem indexItem2'><a href='#remove()'>remove()</a>
    <li class='indexItem indexItem2'><a href='#clear()'>clear()</a>
    <li class='indexItem indexItem2'><a href='#count()'>count()</a>
    <li class='indexItem indexItem2'><a href='#replace_after_get()'>replace_after_get()</a>
    <li class='indexItem indexItem2'><a href='#replace_after_get(%3Cnew_value%3E)'>replace_after_get(&#60;new_value&#62;)</a>
  </ul>
  <li class='indexItem indexItem1'><a href='#ACKNOWLEDGEMENTS'>ACKNOWLEDGEMENTS</a>
  <li class='indexItem indexItem1'><a href='#LICENSE'>LICENSE</a>
  <li class='indexItem indexItem1'><a href='#AUTHOR'>AUTHOR</a>
</ul>
</div>

<h1><a class='u' href='#___top' title='click to go to top of document'
name="NAME"
>NAME</a></h1>

<p><code>Statistics::WeightedSelection</code> - Select a random object according to its weight.</p>

<h1><a class='u' href='#___top' title='click to go to top of document'
name="VERSION"
>VERSION</a></h1>

<p>version 0.002</p>

<h1><a class='u' href='#___top' title='click to go to top of document'
name="SYNOPSIS"
>SYNOPSIS</a></h1>

<pre>    use Statistics::WeightedSelection;

    my $w = Statistics::WeightedSelection-&#62;new();

    # add some objects
    $w-&#62;add(
        object =&#62; &#39;string&#39;,
        weight =&#62; 4,
    );
    $w-&#62;add(
        object =&#62; {p =&#62; 1, q =&#62; 2},
        weight =&#62; 1,
    );
    $w-&#62;add(
        object =&#62; $any_scalar,
        weight =&#62; 7.5,
    );

    # get a random one based upon the individual weight relative to the
    #   combined weight and remove it from the pool for future selection
    #
    #   4 / 12.5 * 100 percent of the time, you&#39;ll get &#39;string&#39;
    #   1 / 12.5 * 100 percent of the time, you&#39;ll get {p =&#62; 1, q =&#62; 2}
    # 7.5 / 12.5 * 100 percent of the time, you&#39;ll get $any_scalar
    my $object = $w-&#62;get();

    # because the last one was removed, the remaining objects are the new
    #   pool for calculating weights and probabilities
    my $another_object = $w-&#62;get();

    # get the number of objects remaining
    my $remaining_object_count = $w-&#62;count();

    # when constructed using replace_after_get and a true value, probababilities
    #   of being selected will remain constant, as after an item is selected,
    #   it is not removed from the pool.
    my $wr = Statistics::WeightedSelection-&#62;new(replace_after_get =&#62; 1);
    #...
    #...
    my $replaced_object = $wr-&#62;get();</pre>

<h1><a class='u' href='#___top' title='click to go to top of document'
name="DESCRIPTION"
>DESCRIPTION</a></h1>

<p>A <code>Statistics::WeightedSelection</code> object is intended to hold unordered objects (at least logically from the caller&#39;s perspective) that each have a corresponding weight. The objects can be any perl scalar or object, and the weights can be any positive integer or floating number.</p>

<p>At any time, an object can be retrieved from the pool. The probability of any object being selected corresponds to its weight divided by the combined weight of all the objects currently in the container.</p>

<p>Objects that are no longer desired to be in the pool can be removed, and an id can be assigned to any of the items to ease in this later removal.</p>

<h1><a class='u' href='#___top' title='click to go to top of document'
name="CAVEATS"
>CAVEATS</a></h1>

<p>An intentional design decision was to use a simple blessed hash to represent the internals of the object, with few direct accessors. The internal <code>_dump()</code> method could be used to see them (with the understanding that internals can change and should not be relied upon in production code), but individual items should not be directly manipulated, and if they are, there&#39;s no guarantee of your success.</p>

<p>Adding and manual deletion should be done through the appropriate methods, <code>add()</code> and <code>remove()</code>, respectively.</p>

<p>I partially did this for speed reasons, and partially to protect people from accidental mishaps. Perhaps I could be persuaded to do so with a sufficiently reasonable argument.</p>

<h1><a class='u' href='#___top' title='click to go to top of document'
name="METHODS"
>METHODS</a></h1>

<h2><a class='u' href='#___top' title='click to go to top of document'
name="CONSTRUCTOR_-_new()"
>CONSTRUCTOR - new()</a></h2>

<p>To create a new cache object, call <code>Statistics::WeightedSelection-&#62;new</code>. It takes the optional arguments listed below.</p>

<dl>
<dt><a name="replace_after_get_(optional)"
><code>replace_after_get</code> (optional)</a></dt>

<dd>
<p>This single configuration, when true, will not remove the object selected from the pool after a call to <code>get()</code>;</p>

<pre>    # replace the object selected with the same object, i.e. don&#39;t remove it.
    my $w = Statistics::WeightedSelection-&#62;new(replace_after_get =&#62; 1);</pre>
</dd>
</dl>

<h2><a class='u' href='#___top' title='click to go to top of document'
name="add()"
>add()</a></h2>

<p>This method is used to add an object and weight to the objects for possible future selection. Two required and one optional arg are described below.</p>

<dl>
<dt><a name="object_(required)"
><code>object</code> (required)</a></dt>

<dd>
<p>The object. Any scalar will do: string, arrayref, hashref, blessed scalar or otherwise.</p>

<dt><a name="weight_(required)"
><code>weight</code> (required)</a></dt>

<dd>
<p>The weight. Integer or float/decimal. Must be greater than 0. This arbitrary number when divided by the total combined weights of the object is the probability that it will be selected on the next call to <code>get()</code>.</p>

<dt><a name="id_(optional)"
><code>id</code> (optional)</a></dt>

<dd>
<p>This is an id that can be used to <code>remove()</code> items later, if desired. It is not required, and the value, if not passed, will default to a serialized version of the object passed (see above).</p>
</dd>
</dl>

<h2><a class='u' href='#___top' title='click to go to top of document'
name="get()"
>get()</a></h2>

<p>Selects an object from the bucket / pool / container randomly, with probabilities of being picked for each item equal to its weight divided by the combined weights.</p>

<p>By default, the object is removed without replacement. <code>replace_after_get()</code> will be called during the course of <code>get()</code>, and if it returns a true value, the item will not be removed.</p>

<p>Returns the randomly selected object.</p>

<p>Takes no arguments.</p>

<h2><a class='u' href='#___top' title='click to go to top of document'
name="remove()"
>remove()</a></h2>

<p>Items that were previously added using <code>add()</code> can be removed from future selection. Either objects that are equivalent (not necessarily a ref to the same object in the container, but one that after serialization is equivalent), or ones that match an id (which was an optional arg for <code>add()</code>) will all be removed.</p>

<p>Returns the removed scalars.</p>

<h2><a class='u' href='#___top' title='click to go to top of document'
name="clear()"
>clear()</a></h2>

<p>Removes all items from the selection pool. A call to <code>get()</code> immediately afterward will return nothing.</p>

<h2><a class='u' href='#___top' title='click to go to top of document'
name="count()"
>count()</a></h2>

<p>The current count of objects that are in the selection pool. It should be noted that sometimes, the same scalar might have been added multiple times with calls to <code>add()</code>, and that those separate instances are all counted separately.</p>

<h2><a class='u' href='#___top' title='click to go to top of document'
name="replace_after_get()"
>replace_after_get()</a></h2>

<p>Returns whether or not a future call to <code>get()</code> will replace the object (i.e. not remove it). If true, the object will not be removed. If false, the object will be removed.</p>

<p>The default behavior, if nothing was passed to the constructor, is to have this return false.</p>

<h2><a class='u' href='#___top' title='click to go to top of document'
name="replace_after_get(&#60;new_value&#62;)"
>replace_after_get(&#60;new_value&#62;)</a></h2>

<p>If <code>replace_after_get()</code> is called with a defined value, this will override the value passed to the constructor (<code>new()</code>), and subsequent calls to <code>replace_after_get()</code> will return this new value.</p>

<p>This sets whether or not an object will be removed from the pool after selection, i.e. a call to <code>get()</code>. If this is truthy, it will remain after a call to <code>get()</code>, and if false, it will not.</p>

<h1><a class='u' href='#___top' title='click to go to top of document'
name="ACKNOWLEDGEMENTS"
>ACKNOWLEDGEMENTS</a></h1>

<p>The ideas encapsulated in this module were created while I was working at Rent.com, a RentPath company. Rent.com has supported me the whole way in releasing this module, and they have fostered an openness in not only utilizing open community tools, but contributing to them, as well.</p>

<p>I&#39;d also like to thank an organization and a few individuals for their contributions:</p>

<dl>
<dt><a name="YAPC_2014_in_Orlando,_Florida"
>YAPC 2014 in Orlando, Florida</a></dt>

<dd>
<p>The conference that finally pushed me to finish this module and make it available.</p>

<dt><a name="Ripta_Pasay"
>Ripta Pasay</a></dt>

<dd>
<p>My manager (and brilliant developer) at Rent, who helped ask the appropriate management at our company about releasing this module without specific, formal policies. He also helped me vet the algorithm and test for problems in randomness on initial and subsequent selections.</p>

<dt><a name="Aran_Deltac"
>Aran Deltac</a></dt>

<dd>
<p>Former Rent.com employee who helped by allowing me to bounce ideas for names and interface of this module, and also to help me search for modules that might have already been written to accomplish a similar purpose.</p>

<dt><a name="Steve_Nolte"
>Steve Nolte</a></dt>

<dd>
<p>Head hauncho of Milwaukee PM who helped steer me in the direction of how to package and manage this module for release.</p>

<dt><a name="Steven_Lembark"
>Steven Lembark</a></dt>

<dd>
<p>For discussing namespaces and name ideas with a total stranger. He really is a testament to how helpful people in the Perl community can be.</p>

<dt><a name="Sawyer_X"
>Sawyer X</a></dt>

<dd>
<p>More discussion of namespaces, and helping to guide me in to whom to talk about such things for further ideas.</p>

<dt><a name="Adam_Dutko"
>Adam Dutko</a></dt>

<dd>
<p>For giving a talk at YAPC to discuss issues about making a module and getting it ready for release on CPAN.</p>
</dd>
</dl>

<h1><a class='u' href='#___top' title='click to go to top of document'
name="LICENSE"
>LICENSE</a></h1>

<p>This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.</p>

<h1><a class='u' href='#___top' title='click to go to top of document'
name="AUTHOR"
>AUTHOR</a></h1>

<p>Alan Voss &#60;alanvoss@hotmail.com&#62;</p>

<!-- end doc -->

</body></html>