Repository: paritytech/substrate
File: frame/election-provider-multi-phase/src/unsigned.rs (Rust)

Code before:
			.map(|(who, stake, _)| (who.clone(), stake))
			.collect::<Vec<_>>();
		voters_sorted.sort_by_key(|(_, y)| *y);
		voters_sorted.reverse();

		// we run through the reduction process twice: once using the size_hint function, and once
		// by actually encoding the data. Given a well-behaved size_hint implementation, this will
		// only actually encode once. Given a misbehaving size_hint implementation, this still ensures
		// that we accurately trim the solution.
		let size_fns: [Box<dyn Fn(&CompactOf<T>) -> u32>; 2] = [
			Box::new(|compact: &CompactOf<T>| compact.size_hint().saturated_into()),
			Box::new(|compact: &CompactOf<T>| {
				let encoded = compact.encode();
				encoded.len().saturated_into()
			}),
		];
		for size_fn in size_fns.iter() {
			while size_fn(&compact) > max_allowed_length {
				let (smallest_stake_voter, _) = voters_sorted.pop().ok_or(MinerError::NoMoreVoters)?;
				let index = voter_index(&smallest_stake_voter).ok_or(MinerError::SnapshotUnAvailable)?;
				compact.remove_voter(index);
			}
		}
		Ok(compact)
	}

	/// Find the maximum `len` that a compact can have in order to fit into the block weight.
	///
	/// This only returns a value between zero and `size.nominators`.
	pub fn maximum_voter_for_weight<W: WeightInfo>(
		desired_winners: u32,
		size: SolutionOrSnapshotSize,
		max_weight: Weight,
	) -> u32 {
		if size.voters < 1 {
			return size.voters;
		}

		let max_voters = size.voters.max(1);
		let mut voters = max_voters;

		// helper closures.
		let weight_with = |active_voters: u32| -> Weight {
			W::submit_unsigned(size.voters, size.targets, active_voters, desired_winners)
		};

		let next_voters = |current_weight: Weight, voters: u32, step: u32| -> Result<u32, ()> {
			match current_weight.cmp(&max_weight) {
				Ordering::Less => {
					let next_voters = voters.checked_add(step);
					match next_voters {

Review comment (refactor):
Given that this code runs offchain, not priority but I can clearly see benefit in merging this and `compact_weight_trim`, given that I think we need to re-do this sorting in both of them, among other duplicate work. 

Maybe you can formulate this as a follow issue for yourself. 

Code after:
	///
	/// Sometimes, removing a voter can cause a validator to also be implicitly removed, if
	/// that voter was the only backer of that winner. In such cases, this solution is invalid, which
	/// will be caught prior to submission.
	///
	/// The score must be computed **after** this step. If this step reduces the score too much,
	/// then the solution must be discarded.
	pub fn trim_compact_length(
		max_allowed_length: u32,
		mut compact: CompactOf<T>,
		voter_index: impl Fn(&T::AccountId) -> Option<CompactVoterIndexOf<T>>,
	) -> Result<CompactOf<T>, MinerError> {
		// short-circuit to avoid getting the voters if possible
		// this involves a redundant encoding, but that should hopefully be relatively cheap
		if (compact.encoded_size().saturated_into::<u32>()) <= max_allowed_length {
			return Ok(compact);
		}

		// grab all voters and sort them by least stake.
		let RoundSnapshot { voters, .. } =
			Self::snapshot().ok_or(MinerError::SnapshotUnAvailable)?;
		let mut voters_sorted = voters
			.into_iter()
			.map(|(who, stake, _)| (who.clone(), stake))
			.collect::<Vec<_>>();
		voters_sorted.sort_by_key(|(_, y)| *y);
		voters_sorted.reverse();

		while compact.encoded_size() > max_allowed_length.saturated_into() {
			let (smallest_stake_voter, _) = voters_sorted.pop().ok_or(MinerError::NoMoreVoters)?;
			let index = voter_index(&smallest_stake_voter).ok_or(MinerError::SnapshotUnAvailable)?;
			compact.remove_voter(index);
		}

		Ok(compact)
	}

	/// Find the maximum `len` that a compact can have in order to fit into the block weight.
	///
	/// This only returns a value between zero and `size.nominators`.
	pub fn maximum_voter_for_weight<W: WeightInfo>(
		desired_winners: u32,
		size: SolutionOrSnapshotSize,
		max_weight: Weight,
	) -> u32 {
		if size.voters < 1 {
			return size.voters;
		}

		let max_voters = size.voters.max(1);
		let mut voters = max_voters;