Lucifer
Lucifer

Reputation: 51

List with each element max 2 times in Python

I have to write a function in Python that takes a list as an input argument and creates a new list where each element can be present 2 times maximum. Inside the function I have to print the number of elements removed from the given list and return a new list, and print the result. If I call the function as list_name([1, 2, 3, 3, 3, 3, 4, 5, 8, 8]) then my desired output should be new_list([1, 2, 3, 3, 4, 5, 8, 8]).

I tried as follows:

def list_name(elements):
output = []
for values in elements:
    if elements.count(values) <= 2 :
        output.append(values)
return output "\n" print(list_name([1, 2, 3, 3, 3, 3, 4, 5, 8, 8]))

Output came as [1, 2, 4, 5, 8, 8]

What should I do?

Upvotes: 0

Views: 1049

Answers (3)

mlisthenewcool
mlisthenewcool

Reputation: 569

Very much faster way to handle this, using the function method_custom().

From O(n+m) to O(n) where n is the input array length and m the output array length.

import random
from typing import List
from timeit import default_timer as timer


def run_test_timings(func, n_repeat, *args):
    start = timer()
    res = [func(*args) for _ in range(n_repeat)]
    end = timer()
    return end - start, res


def method_custom(elements: List[int], exclude_len: int = 2):
    elements_out = list()

    # 0(len(elements) * ~1)
    prev_val, prev_val_counter = None, 0
    for element in elements:
        prev_val_counter = prev_val_counter + 1 if element == prev_val else 0

        if prev_val_counter < exclude_len:
            elements_out.append(element)

        prev_val = element

    return elements_out


def method_count(elements: List[int], exclude_len: int = 2):
    elements_out = []

    # O(len(elements) * len(elements_out))
    for values in elements:
        if elements_out.count(values) < exclude_len:
            elements_out.append(values)

    return elements_out


if __name__ == "__main__":
    N_TESTS = 1_000
    N_ELEMENTS = 1_000
    print(f'N_TESTS    : {N_TESTS}')
    print(f'N_ELEMENTS : {N_ELEMENTS}')

    INPUT_ELEMENTS = sorted([random.randint(0, 100) for _ in range(N_ELEMENTS)])

    print('method_count timer : ', end='')
    timer_1, res_1 = run_test_timings(method_count, N_TESTS, INPUT_ELEMENTS)
    print(timer_1)  # , res_1[0])

    print('method_custom timer : ', end='')
    timer_2, res_2 = run_test_timings(method_custom, N_TESTS, INPUT_ELEMENTS)
    print(timer_2)  # , res_2[0])

Upvotes: 0

Arun K
Arun K

Reputation: 423

def list_name(elements):
   output = []
   removed_items = []
   for values in elements:
       if output.count(values) < 2 :
           output.append(values)
       if elements.count(values)>2 and values not in removed_items:
           removed_items.append(values)      
   return output,removed_items

elements = [1, 2, 3, 3, 3, 3, 4, 5, 8, 8 , 8,9,9,9,9,9]
output , removed_items = list_name(elements)
print(f'Output list : {output}\n')
print(f'Removed Items : {removed_items}\n')
print(f'Orginal List: {elements}\n')

Upvotes: 0

Chris
Chris

Reputation: 29742

You should count the output not the original list:

def list_name(elements):
    output = []
    for values in elements:
        if output.count(values) < 2 : # changed elements.count to output.count and <= to <
            output.append(values)
    return output

Output:

original = [1, 2, 3, 3, 3, 3, 4, 5, 8, 8]
new = list_name(original)
print(len(original) - len(new), new)
# 2 [1, 2, 3, 3, 4, 5, 8, 8]

Upvotes: 3

Related Questions