如何按数组长度占比从m个数组中选取指定数量n的元素?
Let’s break this down using your specific data to make it concrete first:
- Total elements across all arrays: 53 + 23 + 8 + 4 = 88
- Target selection count (n): 18
1. Calculate Proportional Allocation for Each Array
For each array, compute its ideal contribution using the formula:allocation = (array_length / total_elements) * n
Applying this to your arrays:
- arr1: (53/88)*18 ≈ 10.98
- arr2: (23/88)*18 ≈ 4.77
- arr3: (8/88)*18 ≈ 1.64
- arr4: (4/88)*18 ≈ 0.82
2. Adjust for Integer Counts (Since You Can’t Pick a Fraction of an Element)
We can’t select partial elements, so we need to convert these decimals to integers that add up exactly to 18. A fair, reliable method is:
- Take the floor (integer part) of each allocation first: 10, 4, 1, 0 → sum is 15
- Calculate remaining elements to pick: 18 - 15 = 3
- Sort arrays by their fractional parts in descending order: arr1(0.98) > arr4(0.82) > arr2(0.77) > arr3(0.64)
- Add 1 element to the top 3 arrays in this sorted list (to use up the remaining 3 elements):
- arr1 becomes 10 + 1 = 11
- arr4 becomes 0 + 1 = 1
- arr2 becomes 4 + 1 = 5
- Final counts: arr1=11, arr2=5, arr3=1, arr4=1 (sum: 11+5+1+1=18)
Note: Rounding each allocation to the nearest integer might seem simpler, but this can lead to the total sum being more or less than n. The method above guarantees exactly n elements and prioritizes arrays that were closest to earning an extra element via their fractional part.
3. Extract Elements and Combine
Take the first k elements from each array (where k is the final count we calculated), then concatenate them in the order of the original arrays:
- arr1 takes first 11 elements: [1, 2, ..., 11]
- arr2 takes first 5 elements: [54, 55, 56, 57, 58]
- arr3 takes first 1 element: [77]
- arr4 takes first 1 element: [85]
- Combined result: [1, 2, ..., 11, 54, 55, 56, 57, 58, 77, 85]
4. Reusable Code Implementation (Python)
Here’s a function that handles this logic for any number of arrays and target n:
def select_proportional(arrays, n): total_length = sum(len(arr) for arr in arrays) # Track allocations with fractional parts for sorting allocations = [] for idx, arr in enumerate(arrays): proportion = (len(arr) / total_length) * n floor_count = int(proportion) fractional_part = proportion - floor_count # Store negative fractional part to sort ascending (highest first) allocations.append((-fractional_part, idx, floor_count)) # Sort arrays by fractional part descending allocations.sort() remaining_elements = n - sum(count for _, _, count in allocations) # Distribute remaining elements to arrays with highest fractional parts final_counts = [0] * len(arrays) for i in range(len(allocations)): _, arr_idx, floor_count = allocations[i] if remaining_elements > 0: final_counts[arr_idx] = floor_count + 1 remaining_elements -= 1 else: final_counts[arr_idx] = floor_count # Extract and combine elements result = [] for arr, count in zip(arrays, final_counts): result.extend(arr[:count]) return result # Test with your data arr1 = list(range(1, 54)) # 1 to 53 arr2 = list(range(54, 77)) # 54 to 76 arr3 = list(range(77, 85)) #77 to 84 arr4 = list(range(85, 89)) #85 to 88 selected_elements = select_proportional([arr1, arr2, arr3, arr4], 18) print(selected_elements)
This code will output the proportional combined list you need, ensuring exactly 18 elements are selected fairly.
内容的提问来源于stack exchange,提问作者Harish Kommuri

