操作数组的基础算法

# coding=utf-8
import doctest
import collections
from timeit import timeit
from collections.abc import Iterable


# 操作一维数组中多余的数值(限制值为num)【适用短数组】
def array_limit_count_01(array, num):  # 时间复杂度O(n ^ 2)
    """
    根据限制值num ,对列表进行删除操作(每个值最多出现 num次)

    >>> data =[1,2,3,1,2,1,2,3,4]
    >>> array_limit_count_01(data, 2)
    [1, 2, 3, 1, 2, 3, 4]
    """
    ans = []
    for i in array:
        if ans.count(i) < num:
            ans.append(i)
    return ans


# 操作一维数组中多余的数值(限制值为num)【适用长数组】
def array_limit_count_02(array, num):  # 使用哈希表的时间复杂度O(n)。
    """
    根据限制值num ,对列表进行删除操作(每个值最多出现 num次)

    >>> data =[1,2,3,1,2,1,2,3,4]
    >>> array_limit_count_02(data, 2)
    [1, 2, 3, 1, 2, 3, 4]
    """
    result = []
    counts = collections.defaultdict(int)
    for i in array:
        if counts[i] < num:
            result.append(i)
            counts[i] += 1
    return result


# 把多维数组变成一维数组【适用短数组】
def array_flatten_01(input_arr, output_arr=None):
    """
    把多维数组变成一维数组,返回一个列表

    >>> data = [1, [1, ], 2, [5, ],[3, 4, [6, ], 6], 8, ]
    >>> array_flatten_01(data)
    [1, 1, 2, 5, 3, 4, 6, 6, 8]
    """
    if output_arr is None:
        output_arr = []
    for ele in input_arr:
        # 检查是否可迭代
        if isinstance(ele, Iterable):
            array_flatten_01(ele, output_arr)
        else:
            output_arr.append(ele)
    return output_arr


# 把多维数组变成一维数组【适用长数组】
def array_flatten_02(iterable):
    """
    把多维数组变成一维数组,返回一个迭代器

    >>> data = [1, [1, ], 2, [5, ], [3, 4, [6, ], 6], 8, ]
    >>> result = array_flatten_02(data)
    >>> next(result)
    1
    >>> list(result)
    [1, 2, 5, 3, 4, 6, 6, 8]
    """
    for element in iterable:
        # 检查是否可迭代
        if isinstance(element, Iterable):
            yield from array_flatten_02(element)
        else:
            yield element


# 类似打乱数组里的元素位置,再把打乱的数据恢复
def array_restore(initial_arr, final_arr):
    """
    initial_arr:初始状态 final_arr:最终状态
    把【initial_arr】变成【final_arr】

    例子:车库的停车场(每个场地的编号)
        把场地重新划分

    >>> initial_arr = [1, 2, 3, 0, 4]
    >>> final_arr = [0, 3, 2, 1, 4]
    >>> array_restore(initial_arr, final_arr) # 结果为:恢复步骤次数和过程
    (4, [[0, 3, 2, 1, 4], [0, 2, 3, 1, 4], [2, 0, 3, 1, 4], [2, 3, 0, 1, 4], [0, 3, 2, 1, 4]])
    """
    initial = initial_arr[::]  # 拷贝数据(id不一样)
    seq = []  # 依次列出每个步骤
    seq.append(initial)
    steps = 0
    while initial != final_arr:
        zero = initial.index(0)
        # 如果initial数组的0所在的下标 不等于 final数组的0所在的下标
        if zero != final_arr.index(0):  # 如果零不在应该的位置,
            car_to_move = final_arr[zero]
            pos = initial.index(car_to_move)
            initial[zero], initial[pos] = initial[pos], initial[zero]
        else:
            for i in range(len(initial)):
                # 如果值不相等就退出循环(根据下标对应的值)
                if initial[i] != final_arr[i]:
                    initial[zero], initial[i] = initial[i], initial[zero]
                    break
        seq.append(initial[::])
        steps += 1

    return steps, seq


# 对数组重新排序(改变值的位置)
def array_rearrange(int_arr, skip, index=0):
    """
    根据skip 重组数组的位置

    :param skip:  跳跃的步长
    :param index: 存放索引的,不需要传入

    >>> int_arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> result = array_rearrange(int_arr, 3)
    >>> next(result)
    3
    >>> list(result)
    [6, 9, 4, 8, 5, 2, 7, 1]
    """
    skip = skip - 1  # 列表以0索引开头
    len_list = (len(int_arr))
    while len_list > 0:
        index = (skip + index) % len_list
        yield int_arr.pop(index)
        len_list -= 1


# 在一维数组中找出限定值
def array_limit(arr, min_lim=None, max_lim=None):
    """
    在一维数组中找出限定值

    :param min_lim: 最小值
    :param max_lim: 最大值

    >>> array_limit([1,2,3,4,5], None, 3)
    [1, 2, 3]
    >>> array_limit([2, 5, 1, 2, 3, 4, 5], 2, 3)
    [2, 2, 3]
    """
    # 检验最小值的匿名函数
    min_check = lambda val: True if min_lim is None else (min_lim <= val)
    # 检验最大值的匿名函数
    max_check = lambda val: True if max_lim is None else (val <= max_lim)
    return [val for val in arr if min_check(val) and max_check(val)]


if __name__ == '__main__':
    doctest.testmod( )
    doctest.testfile("doc.txt")

    """
    stmt = "array_limit([1,2,3,4,5], None, 3)"
    setup = "from __main__ import array_limit"
    cost_time = timeit(stmt, setup, number = 10000)
    print(cost_time)  # 0.020091733
    
    stmt = "array_rearrange([1, 2, 3, 4, 5, 6, 7, 8, 9], 3)"
    setup = "from __main__ import array_rearrange"
    cost_time = timeit(stmt, setup, number = 10000)
    print(cost_time)  # 0.0033079469999999916
    
    stmt = "array_restore([1, 2, 3, 0, 4], [0, 3, 2, 1, 4])"
    setup = "from __main__ import array_restore"
    cost_time = timeit(stmt, setup, number = 10000)
    print(cost_time)  # 0.041407573
    
    stmt = "array_flatten_01([1, [1, ], 2, [5, ], [3, 4, [6, ], 6], 8, ])"
    setup = "from __main__ import array_flatten_01"
    cost_time = timeit(stmt, setup, number = 10000)
    print(cost_time)  # 0.07394432000000001

    stmt = "array_flatten_02([1, [1, ], 2, [5, ], [3, 4, [6, ], 6], 8, ])"
    setup = "from __main__ import array_flatten_02"
    cost_time = timeit(stmt, setup, number = 10000)
    print(cost_time)  # 0.0046058670000000135

    stmt = 'array_limit_count_01([1,2,3,1,2,1,2,3,4],2)'
    setup = 'from __main__ import array_limit_count_01'
    cost_time = timeit(stmt, setup, number = 10000)
    print(cost_time)  # 0.016674133999999993

    stmt = 'array_limit_count_02([1,2,3,1,2,1,2,3,4],2)'
    setup = 'from __main__ import array_limit_count_02'
    cost_time = timeit(stmt, setup, number = 10000)
    print(cost_time)  # 0.027026773000000004【适用长数组】
    """

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值