I'm writing code to create a list of new areas for patches of conserved land within a watershed based on the current size distribution of conserved land patches that are in the watershed now. I'm generating a new random area based on a normal probability density function fitted to the log-transformed distribution of the sizes of currently conserved land. Then I have a list of the areas of tax parcels in the region, and I want to randomly grab a tax parcel that is within  10% of the randomly generated area. The loop will continue until I've generated a total 4,735 hectares of new areas for conservation.The code works, and runs very quickly if I lower the threshold for total new conserved area to ~500 hectares. However, for my current endpoint (4,735 new hectares), it runs so slowly that I haven't actually ever run it all the way through (waited an hour+). Any ideas on how I can streamline this code to get it to run faster are greatly appreciated!# Set endpoint of total new areanew_cons_area = 4735.44# Get new random areas until they total the new_cons_areasum_rand_area = 0new_rand_area = []rand_sizes = []index_list = []while sum_rand_area < new_cons_area:    # Get new random size based on current distribution of sizes of conservation patches    new_log_size = np.random.normal(param_log[0],param_log[1],1)    # Transform back to actual area    new_size = np.e**new_log_size[0]    # Set buffer boundaries    min_size = new_size * 0.9    max_size = new_size * 1.1    # Get length of new_rand_area list    current_length = len(new_rand_area)    # Set up loop to grab sizes from the current list of tax parcels suitable for conservation    if new_size >= 3.33:        # Run this loop until a new size is added to the list of new random areas        while len(new_rand_area) == current_length:            # Grab a random index from the list of parcel areas            rand_index = random.randrange(len(parcel_areas)-1)            # See if the parcel area associated with the random index matches the randomly generated size            if min_size <= parcel_areas[rand_index] <= max_size:                # If criteria is met, add the randomly generated size to a list                rand_sizes.append(int(new_size))                # Add the randomly generated index to list so you can grab the object ids in the next step                index_list.append(rand_index)                # Add the actual tax parcel area to a list                new_rand_area.append(parcel_areas[rand_index])                # Add the area to the total area of new land to be conserved                sum_rand_area += parcel_areas[rand_index]
Creating a list of new areas for patches of conserved land within a watershed
python;random;time limit exceeded
The problem is that random.randrange(len(parcel_areas)-1) most of the times returns an area which fails the min_size <= parcel_areas[rand_index] <= max_size test. Therefore it is logical to restrict the random selection to the set of areas which satisfy the requirements beforehand, and eliminate the inner loop completely.Sort the list of areas by size. Once you determined min_size and max_size, find corresponding bounds (with binary search), and select randomly within these bounds.