Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中将值强制转换为各自数据类型的最快方法_Python_Performance_Casting - Fatal编程技术网

在Python中将值强制转换为各自数据类型的最快方法

在Python中将值强制转换为各自数据类型的最快方法,python,performance,casting,Python,Performance,Casting,我有一个值列表-所有字符串。我想将这些值转换为各自的数据类型。我将值映射到可用的类型信息 有三种不同的数据类型:int、str和datetime。 代码需要能够处理带有数据的错误情况 我正在做一些类似于:- tlist = [ 'some datetime value', '12', 'string', .... ] #convert it to: [ datetime object, 12, 'string', ....] error_data = ['', ' ', '?', ...]

我有一个值列表-所有字符串。我想将这些值转换为各自的数据类型。我将值映射到可用的类型信息

有三种不同的数据类型:int、str和datetime。 代码需要能够处理带有数据的错误情况

我正在做一些类似于:-

tlist =  [ 'some datetime value', '12', 'string', .... ]

#convert it to: [ datetime object, 12, 'string', ....]

error_data = ['', ' ', '?', ...]

d = { 0: lambda x: datetime.strptime(x,...) if x not in error_data else x, 
      1: lambda x: int(x) if x not in error_data else 0,
      2: lambda x: x 
      ...
     }

result = [ d[i](j) for i, j in enumerate(tlist) ]
要转换的列表非常长,比如180个值,我需要对数千个这样的列表进行转换。上述代码的性能非常差。最快的方法是什么


谢谢

因为您知道要转换到的类型,所以您可能无法从尝试优化转换中获得性能提升。性能不佳可能是由于反复迭代
错误\u数据
。如果可能,将您的
错误\u数据
列表重建为
集合
,以利用该类型的性质:

error_set = set((err, None) for err in error_data)

那就照你一直做的去做吧。进一步的改进需要对代码进行分析,以确定实际花费的时间。

我不知道这是否会更快,但对我来说更清楚:

tlist =  [ 'some datetime value', '12', 'string', .... ]

#convert it to: [ datetime object, 12, 'string', ....]

error_data = set(['', ' ', '?', ...])

def s(x):
    return x

def d(x):
    return datetime(x) if x not in error_data else x

def i(x):
    return int(x) if x not in error_data else 0

types = [ d, i, s, s, s, i, i, d, i, ... ]

result = [ t(x) for t, x in zip(types, tlist) ]
正如其他人提到的,我正在使用一组错误值,这将比您的列表更快。

类似于:

>>> values = ["12", "a", "bcd", "2.2"]
>>> types = [int, int, str, float]
>>> defaults = {int: 0, float: 0.0}
>>> res = []
>>> for v, f in itertools.izip(values, types): #Just use zip for Python 3+.
    try:
        res.append(f(v))
    except ValueError:
        res.append(defaults[f])
>>> print(res)
[12, 0, 'bcd', 2.2]
编辑:

这不处理日期时间值。我的解决方案是使用
str
,并在循环后转换为datetime,如:

res[0] = datetime.strptime(res[0], "...")

获取和设置列表项都有O(1)复杂性,因此这应该不是问题。

如果您的datetime值始终一致,为什么不让类型转换处理您试图在错误数据中管理的无效数据呢。这并不像某些解决方案那个么吸引人,但它使基于列表中数据的位置管理类型转换更易于维护和扩展

def convert(position, val):
    if position == 0:
        try:
            return datetime.strptime(val, '%Y-%m-%d %H:%M:%S') # assuming date is in a constant format
        except ValueError:
            return val
    elif position in (1, 15, 16): # assuming that you have other int values in other "columns"
        try:
            return int(val)
        except ValueError:
            return 0
    else: # string type
       return val

result = [convert(i,j) for i, j in enumerate(tlist)]

您的代码中存在不一致之处:

如果列表中的所有元素都是字符串,则不能在x为字符串的情况下编写
datetime(x)

编辑 它没有描绘任何东西,因为它是不协调的。代码中不存在的内容的复杂性并不能证明代码中存在的奇怪之处。我想,只要您不解释如何将字符串作为参数传递给函数datetime.datetime(),就没有人能够帮助您

编辑 我认为最好在读取文件时直接创建列表

我写了一个例子:

首先,我用以下代码创建了一个CSV文件:

import csv
from random import randint,choice
from time import gmtime


xx = ['Whose', 'all', 'birth', 'just', 'infant', 'William',
      'dearest', 'rooms', 'find', 'Deserts', 'saucy', 'His',
      'how', 'considerate', 'only', 'other', 'Houses', 'has',
      'Fanny', 'them', 'his', 'very', 'dispense', 'early',
      'words', 'not', 'thus', 'now', 'pettish', 'Worth']

def gen(n):
    for i in xrange(n):
        yield ['AAAA','%d/%02d/%02d %02d:%02d:%02d' % gmtime(randint(0,80000000))[0:6],'@@@']
        yield ['BBBB',randint(100,999),'^^^^^^']
        yield ['CCCC',choice(xx),'-----------------']

with open('zzz.txt','wb') as f:
    writ = csv.writer(f, delimiter='#')
    writ.writerows(x for x in gen(60))
CSV文件的结构如下所示:

AAAA#1972/02/11 08:53:53#@@@
BBBB#557#^^^^^^
CCCC#dearest#-----------------
AAAA#1971/10/15 06:55:20#@@@
BBBB#668#^^^^^^
CCCC#?#-----------------
AAAA#1972/07/13 11:10:05#@@@
BBBB#190#^^^^^^
CCCC#infant#-----------------
AAAA#1971/11/22 19:31:42#@@@
BBBB#202#^^^^^^
CCCC##-----------------
AAAA#1971/06/12 05:48:39#@@@
BBBB#81#^^^^^^
CCCC#find#-----------------
AAAA#1970/12/09 06:26:29#@@@
BBBB#72#^^^^^^
CCCC#find#-----------------
AAAA#1972/07/05 10:45:32#@@@
BBBB#270#^^^^^^
CCCC#rooms#-----------------
AAAA#1972/06/23 05:52:20#@@@
BBBB#202#^^^^^^
CCCC##-----------------
AAAA#1972/03/21 23:06:47#@@@
BBBB#883#^^^^^^
CCCC#William#-----------------
...... etc

下面的代码以与所需类似的方式提取数据

不需要字典,一个元组就足够了。根据创建的CSV文件的结构,我定义了
funcs=60*(to_dt,int,lambda x:x)
,但您将使用字典值(排序)的连续函数

结果

1972-02-11 08:53:53    557     dearest
1971-10-15 06:55:20    668           ?
1972-07-13 11:10:05    190      infant
1971-11-22 19:31:42    202            
1971-06-12 05:48:39     81        find
1970-12-09 06:26:29     72        find
1972-07-05 10:45:32    270       rooms
1972-06-23 05:52:20    202            
1972-03-21 23:06:47    883     William
1970-02-08 23:47:26    617            
1970-10-08 09:09:33    387     William
1971-04-30 11:05:07    721           ?
1970-02-12 11:57:48    827     Deserts
1972-03-27 21:30:39    363        just
1971-06-02 00:23:52    977            
1970-04-20 04:38:38    113     William
1971-01-20 23:10:26     75       Whose
1971-07-01 12:46:13    352     dearest
1971-01-31 17:01:34    220     William
1970-06-09 20:38:52    148       rooms
1971-08-08 07:42:10    146            
1970-01-28 15:17:41    903        find
...............etc

作为utdemir答案的一个变体,如果错误值非常罕见,那么您可以优化常见情况:

>>> values = ["12", "a", "bcd", "2.2"]
>>> types = [int, int, str, float]
>>> defaults = {int: 0, float: 0.0}
>>> try: res = [f(v) for v,f in zip(values,types)]
... except: 
...     res = []
...     for v, f in zip(values, types):
...        try:
...             res.append(f(v))
...         except ValueError:
...             res.append(defaults[f])

即,首先尝试转换整条线路,假设不会出现任何问题。如果出现任何错误,请返回并一次转换一个值,修复所有错误值。

感谢所有这些方法。是的,我几乎尝试了所有提到的方法,但没有一种表现得很好

我尝试了以下方法,它非常适合我的性能需求。这就是我所做的

  • 我按照utdemir的建议处理了datetime值
  • 我为所有int错误值插入了值0,代码如下-

    [i]=如果值为,则为值!=''其他0

  • 我没有使用dictionary逐个强制值,而是使用列表一次强制所有值

    
    def强制(l):
    返回[l[0],int(l[1]),int(l[2])…]

  • 我的意见:

  • 单独处理错误案例并立即强制执行会有很大帮助
  • 让代码从异常中恢复需要很多时间
  • 多次查看一个列表并没有什么坏处(我这样做是为了处理错误案例)
  • 给出一个想法,对于几个小时的数据(60万条记录),我的方法将运行时间从6-7分钟缩短到了2m30s

  • 你知道你想要的类型映射吗?i、 e.您是否总是知道
    tlist[0]
    应该是
    datetime
    ,等等?是的,我知道类型的映射。您是从数据库获取值的吗?我从simpledb读取这些值,simpledb以纯CSV格式存储这些值。所以当我读取值时,我会得到CSV值。我将这些CSV值转换为单独的列表,然后任务是将其转换为上面提到的内容。
    error\u data
    需要多长时间?如果它很长,将其转换为
    会加快速度。我在发布答案后立即看到了你的评论,并相应地进行了更新。我喜欢使用try/except。由于问题是要求优化,我将使用
    itertools.izip
    而不是
    zip
    。这是如何处理日期时间转换的?这看起来是正确的方法,我将立即尝试并让大家知道。谢谢。@utdemir定义了另一个问题(out是datetime字符串),这使得它很容易解决。显然,从异常中恢复需要很大的性能损失。我仍然在测试我的代码——仍然在按照您的建议实现代码之后,它需要更多的时间来运行。我会让每个人都知道我的发现。。这里的问题是如何将所有这些值转换为各自的类型。。。实际代码是非常复杂的数据收集框架的一部分,因此我无法复制/粘贴它。我只想写代码的相关部分,描述问题。
    >>> values = ["12", "a", "bcd", "2.2"]
    >>> types = [int, int, str, float]
    >>> defaults = {int: 0, float: 0.0}
    >>> try: res = [f(v) for v,f in zip(values,types)]
    ... except: 
    ...     res = []
    ...     for v, f in zip(values, types):
    ...        try:
    ...             res.append(f(v))
    ...         except ValueError:
    ...             res.append(defaults[f])