def _extract_actions_unique_topics(self, movement_counts, max_movements, cluster_topology, max_movement_size):
        """Extract actions limiting to given max value such that
           the resultant has the minimum possible number of duplicate topics.

           Algorithm:
           1. Group actions by by topic-name: {topic: action-list}
           2. Iterate through the dictionary in circular fashion and keep
              extracting actions with until max_partition_movements
              are reached.
           :param movement_counts: list of tuple ((topic, partition), movement count)
           :param max_movements: max number of movements to extract
           :param cluster_topology: cluster topology containing the new proposed assignment for the cluster
           :param max_movement_size: maximum size of data to move at a time in extracted actions
           :return: list of tuple (topic, partitions) to include in the reduced plan
        """
        # Group actions by topic
        topic_actions = defaultdict(list)
        for t_p, replica_change_cnt in movement_counts:
            topic_actions[t_p[0]].append((t_p, replica_change_cnt))

        # Create reduced assignment minimizing duplication of topics
        extracted_actions = []
        curr_movements = 0
        curr_size = 0
        action_available = True
        while curr_movements < max_movements and curr_size <= max_movement_size and action_available:
            action_available = False
            for topic, actions in six.iteritems(topic_actions):
                for action in actions:
                    action_size = cluster_topology.partitions[action[0]].size
                    if curr_movements + action[1] > max_movements or curr_size + action_size > max_movement_size:
                        # Remove action since it won't be possible to use it
                        actions.remove(action)
                    else:
                        # Append (topic, partition) to the list of movements
                        action_available = True
                        extracted_actions.append(action[0])
                        curr_movements += action[1]
                        curr_size += action_size
                        actions.remove(action)
                        break
        return extracted_actions
Extract actions limiting to given max value such that
           the resultant has the minimum possible number of duplicate topics.

           Algorithm:
           1. Group actions by by topic-name: {topic: action-list}
           2. Iterate through the dictionary in circular fashion and keep
              extracting actions with until max_partition_movements
              are reached.
           :param movement_counts: list of tuple ((topic, partition), movement count)
           :param max_movements: max number of movements to extract
           :param cluster_topology: cluster topology containing the new proposed assignment for the cluster
           :param max_movement_size: maximum size of data to move at a time in extracted actions
           :return: list of tuple (topic, partitions) to include in the reduced plan