GVKun编程网logo

在'if'子句中使用'in'时的元组或列表?(if in语句)

11

此处将为大家介绍关于在'if'子句中使用'in'时的元组或列表?的详细内容,并且为您解答有关ifin语句的相关问题,此外,我们还将为您介绍关于c#–为什么在这个例子中使用比元组更快的元组?、c#–在列

此处将为大家介绍关于在'if'子句中使用'in'时的元组或列表?的详细内容,并且为您解答有关if in语句的相关问题,此外,我们还将为您介绍关于c# – 为什么在这个例子中使用比元组更快的元组?、c# – 在列表中搜索数组或列表、Java 中的数组或列表。哪个更快?、Java 中的数组或列表哪个更快?的有用信息。

本文目录一览:

在'if'子句中使用'in'时的元组或列表?(if in语句)

在'if'子句中使用'in'时的元组或列表?(if in语句)

哪种方法更好?使用元组,例如:

if number in (1, 2):

或清单,例如:

if number in [1, 2]:

建议将哪一种用于此类用途,以及为什么使用(出于逻辑和性能考虑)?

答案1

小编典典

CPython解释器 将第二种形式替换为第一种形式

这是因为从常量加载元组是一个操作,但是列表将是3个操作;加载两个整数内容并构建一个新的列表对象。

由于您使用的是无法到达的列表文字,因此它将替换为元组:

>>> import dis>>> dis.dis(compile(''number in [1, 2]'', ''<stdin>'', ''eval''))  1           0 LOAD_NAME                0 (number)              3 LOAD_CONST               2 ((1, 2))              6 COMPARE_OP               6 (in)              9 RETURN_VALUE

这里第二字节码负载一个(1, 2)元组为常数,在 一个 步骤。将其与创建成员资格测试中未使用的列表对象进行比较:

>>> dis.dis(compile(''[1, 2]'', ''<stdin>'', ''eval''))  1           0 LOAD_CONST               0 (1)              3 LOAD_CONST               1 (2)              6 BUILD_LIST               2              9 RETURN_VALUE

对于长度为N的列表对象,需要N + 1个步骤。

这种替换是CPython特有的窥孔优化。见Python/peephole.c资料来源。然后,对于
其他 Python实现,您要坚持使用不可变的对象。

也就是说,在使用Python 3.2及更高版本时, 最好的 选择是使用 set文字

if number in {1, 2}:

因为窥视孔优化器将用frozenset()对象代替它,并且针对集合的成员资格测试是O(1)常数操作:

>>> dis.dis(compile(''number in {1, 2}'', ''<stdin>'', ''eval''))  1           0 LOAD_NAME                0 (number)              3 LOAD_CONST               2 (frozenset({1, 2}))              6 COMPARE_OP               6 (in)              9 RETURN_VALUE

此优化是在Python
3.2中添加的,但并未反向移植到Python
2。

因此,Python 2优化器无法识别此选项,并且几乎可以肯定构建asetfrozenset从内容构建的成本比使用元组进行测试的成本更高。

集合成员资格测试是O(1)且快速;对元组进行测试是O(n)最坏的情况。尽管针对集合进行测试必须计算哈希(较高的不变成本,为不可变类型缓存),但是针对
除第一个元素之外的 元组进行测试的成本始终会更高。因此,平均而言,集合可以轻松地更快:

>>> import timeit>>> timeit.timeit(''1 in (1, 3, 5)'', number=10**7)  # best-case for tuples0.21154764899984002>>> timeit.timeit(''8 in (1, 3, 5)'', number=10**7)  # worst-case for tuples0.5670104179880582>>> timeit.timeit(''1 in {1, 3, 5}'', number=10**7)  # average-case for sets0.2663505630043801>>> timeit.timeit(''8 in {1, 3, 5}'', number=10**7)  # worst-case for sets0.25939063701662235

c# – 为什么在这个例子中使用比元组更快的元组?

c# – 为什么在这个例子中使用比元组更快的元组?

我写了一个C#类,用一些数据填充“双打列表列表”(无论数据是什么,现在它可能只是一些垃圾:)),用于测试目的:

这是代码:

class test
    {
    public test()
    {
       _mylistofList = new List<List<double>>(1000000);
    }
    public void Run()
    {
        for (int i = 0; i < _mylistofList.Capacity; i++)
        {
            _mylistofList.Add(
                new List<double>(3) { i,10*i,100*i}
                ); //Populate the list with data
        }
    }

    private List<List<double>> _mylistofList;
}

我将此代码的执行速度与以下内容进行了比较:(用元组替换double的列表)

class test
    {
    public test()
    {
       _mylistofTuple = new List<Tuple<double,double,double>>(1000000);
    }
    public void Run()
    {
        for (int i = 0; i < _mylistofTuple.Capacity; i++)
        {
            _mylistofTuple.Add(
                new Tuple<double,double>(i,10 * i,100 * i)
                ); //Populate the list with data
        }
    }

    private List<Tuple<double,double>> _mylistofTuple;
}

事实证明,使用元组似乎要快得多.我为不同的List大小运行了这段代码(从200,000个元素 – 列表中的> 5百万个元素),这是我得到的结果:

我无法真正理解这一点.为什么我会有如此显着的差异?使用存储相同类型对象的元组(这里加倍)并没有多大意义.我宁愿使用List /数组来做到这一点:我做错了什么?是否有一种方法可以使案例#1以比案例#2更快/更快的速度运行?

谢谢!

解决方法

新元组< double,100 * i)和新List< double>(3){i,100 * i}之间存在差异.

第一个是超级简单 – 只有3个任务:

public Tuple(T1 item1,T2 item2,T3 item3) {
    m_Item1 = item1;
    m_Item2 = item2;
    m_Item3 = item3;
}

第二个实际上是由编译器转换为3个Add方法调用:

var temp = new List<double>(3);
temp.Add(i);
temp.Add(10 * i);
temp.Add(100 * i);

添加不仅仅是一项任务:

public void Add(T item) {
    if (_size == _items.Length) EnsureCapacity(_size + 1);
    _items[_size++] = item;
    _version++;
}

运行更多代码,执行速度更慢.非常简单..

c# – 在列表中搜索数组或列表

c# – 在列表中搜索数组或列表

List<byte> lbyte

byte[] searchBytes

如何搜索lbyte不仅仅是一个字节,而是搜索searchBytes的索引?
例如.

Int32 index = lbyte.FirstIndexOf(searchBytes);

这是我提出的蛮力.
不是我要找的表现.

public static Int32 ListIndexOfArray(List<byte> lb,byte[] sbs)
{
    if (sbs == null) return -1;
    if (sbs.Length == 0) return -1;
    if (sbs.Length > 8) return -1;
    if (sbs.Length == 1) return lb.FirstOrDefault(x => x == sbs[0]);
    Int32 sbsLen = sbs.Length;
    Int32 sbsCurMatch = 0;
    for (int i = 0; i < lb.Count; i++)
    {
        if (lb[i] == sbs[sbsCurMatch])
        {
            sbsCurMatch++;
            if (sbsCurMatch == sbsLen)
            {
                //int index = lb.Findindex(e => sbs.All(f => f.Equals(e)));  // fails to find a match
                IndexOfArray = i - sbsLen + 1;
                return;
            }
        }
        else 
        {
            sbsCurMatch = 0;
        }
    }
    return -1;
}

解决方法

你可能会发现 Boyer-Moore algorithm在这里很有用.将列表转换为数组并进行搜索.算法代码取自 this post.
static int SimpleBoyerMooreSearch(byte[] haystack,byte[] needle)
{
    int[] lookup = new int[256];
    for (int i = 0; i < lookup.Length; i++) { lookup[i] = needle.Length; }

    for (int i = 0; i < needle.Length; i++)
    {
        lookup[needle[i]] = needle.Length - i - 1;
    }

    int index = needle.Length - 1;
    var lastByte = needle.Last();
    while (index < haystack.Length)
    {
        var checkByte = haystack[index];
        if (haystack[index] == lastByte)
        {
            bool found = true;
            for (int j = needle.Length - 2; j >= 0; j--)
            {
                if (haystack[index - needle.Length + j + 1] != needle[j])
                {
                    found = false;
                    break;
                }
            }

            if (found)
                return index - needle.Length + 1;
            else
                index++;
        }
        else
        {
            index += lookup[checkByte];
        }
    }
    return -1;
}

然后你可以这样搜索.如果lbyte在一段时间后保持不变,你可以将它转换为一个数组并传递它.

//index is returned,or -1 if 'searchBytes' is not found
int startIndex = SimpleBoyerMooreSearch(lbyte.ToArray(),searchBytes);

根据评论更新.这是IList实现,这意味着可以传递数组和列表(以及实现IList的任何其他内容)

static int SimpleBoyerMooreSearch(IList<byte> haystack,IList<byte> needle)
 {
    int[] lookup = new int[256];
    for (int i = 0; i < lookup.Length; i++) { lookup[i] = needle.Count; }

    for (int i = 0; i < needle.Count; i++)
    {
        lookup[needle[i]] = needle.Count - i - 1;
    }

    int index = needle.Count - 1;
    var lastByte = needle[index];
    while (index < haystack.Count)
    {
        var checkByte = haystack[index];
        if (haystack[index] == lastByte)
        {
            bool found = true;
            for (int j = needle.Count - 2; j >= 0; j--)
            {
                if (haystack[index - needle.Count + j + 1] != needle[j])
                {
                    found = false;
                    break;
                }
            }

            if (found)
                return index - needle.Count + 1;
            else
                index++;
        }
        else
        {
            index += lookup[checkByte];
        }
    }
    return -1;
}

由于数组和列表实现了IList,因此在您的情况下调用它时不需要进行转换.

int startIndex = SimpleBoyerMooreSearch(lbyte,searchBytes);

Java 中的数组或列表。哪个更快?

Java 中的数组或列表。哪个更快?

我必须在内存中保留数千个字符串,以便在 Java 中连续访问。我应该将它们存储在数组中还是应该使用某种 List ?

由于数组将所有数据保存在连续的内存块中(与列表不同),使用数组存储数千个字符串会导致问题吗?

Java 中的数组或列表哪个更快?

Java 中的数组或列表哪个更快?

我必须在内存中保留数千个字符串,以便在 Java 中连续访问。我应该将它们存储在数组中还是应该使用某种 List ?

由于数组将所有数据保存在连续的内存块中(与列表不同),使用数组存储数千个字符串会导致问题吗?

今天关于在'if'子句中使用'in'时的元组或列表?if in语句的分享就到这里,希望大家有所收获,若想了解更多关于c# – 为什么在这个例子中使用比元组更快的元组?、c# – 在列表中搜索数组或列表、Java 中的数组或列表。哪个更快?、Java 中的数组或列表哪个更快?等相关知识,可以在本站进行查询。

本文标签: