按键值拆分字典列表-与pop一样?

时间:2019-01-24 10:02:44

标签: python

我见过Python: remove dictionary from listSplitting a list of dictionaries into several lists of dictionaries-但是这个问题略有不同。

考虑以下工作示例(与Python 2或3相同):

#!/usr/bin/env python
from __future__ import print_function

origarr = [
  { 'name': 'test01', 'type': 0, 'value': 42 },
  { 'name': 'test02', 'type': 0, 'value': 142 },
  { 'name': 'test03', 'type': 2, 'value': 242 },
  { 'name': 'test04', 'type': 2, 'value': 342 },
  { 'name': 'test05', 'type': 3, 'value': 42 },
]

print("origarr: {}".format(origarr))

lastdictelem = origarr.pop()

print("\nlastdictelem: {}".format(lastdictelem))
print("after pop, origarr: {}".format(origarr))

namestofilter = [ 'test01', 'test02' ]
newarr = []
for iname in namestofilter:
  # find the object having the name iname
  foundidx = -1
  for ix, idict in enumerate(origarr):
    if idict.get('name') == iname:
      foundidx = ix
      break
  if foundidx > -1:
    # remove dict object via pop at index, save removed object
    remdict = origarr.pop(foundidx)
    # add removed object to newarr:
    newarr.append(remdict)

print("\nafter namestofilter:")
print("newarr: {}".format(newarr))
print("origarr: {}".format(origarr))

基本上,mylist.pop()mylist中删除最后一个元素作为对象(这里是字典),然后将其返回-然后,我可以将其琐碎地插入新的数组/列表中;此脚本的第一次打印输出对此进行了说明:

$ python2 test.py 
origarr: [{'name': 'test01', 'type': 0, 'value': 42}, {'name': 'test02', 'type': 0, 'value': 142}, {'name': 'test03', 'type': 2, 'value': 242}, {'name': 'test04', 'type': 2, 'value': 342}, {'name': 'test05', 'type': 3, 'value': 42}]

lastdictelem: {'name': 'test05', 'type': 3, 'value': 42}
after pop, origarr: [{'name': 'test01', 'type': 0, 'value': 42}, {'name': 'test02', 'type': 0, 'value': 142}, {'name': 'test03', 'type': 2, 'value': 242}, {'name': 'test04', 'type': 2, 'value': 342}]

现在,我想做的是定义一个包含dict中的name键值(例如namestofilter = [ 'test01', 'test02' ])的数组,并将这些dict从原始数组/列表中删除,并放入新的数组/列表中(就像.pop()可以处理单个元素和对象引用一样。)

pop removes the item at a specific index and returns it起,以上代码正是这样做的-并且有效:

...
after namestofilter:
newarr: [{'name': 'test01', 'type': 0, 'value': 42}, {'name': 'test02', 'type': 0, 'value': 142}]
origarr: [{'name': 'test03', 'type': 2, 'value': 242}, {'name': 'test04', 'type': 2, 'value': 342}]

...但是我想知道-除了“手动” for循环遍历两个数组并调用.pop() / {{1}之外,还有没有更紧凑的方法可以做到这一点? }(如示例中所示)?

1 个答案:

答案 0 :(得分:1)

我不确定是否有紧凑的方法-可能没有。

但是您可以简化一些代码,也不必为每个O(n)花费.pop

origarr = [
  { 'name': 'test01', 'type': 0, 'value': 42 },
  { 'name': 'test02', 'type': 0, 'value': 142 },
  { 'name': 'test03', 'type': 2, 'value': 242 },
  { 'name': 'test04', 'type': 2, 'value': 342 },
  { 'name': 'test05', 'type': 3, 'value': 42 },
]

namestofilter = set([ 'test01', 'test02' ]). # could be a list as in question
print("origarr: {}".format(origarr))

lastdictelem = origarr.pop()

print("\nlastdictelem: {}".format(lastdictelem))
print("after pop, origarr: {}".format(origarr))

shift = 0
newarr = []
for ix, idict in enumerate(origarr):
    if idict['name'] in namestofilter:
        shift += 1
        newarr.append(idict)
        continue
    origarr[ix-shift] = origarr[ix]
origarr = origarr[:-shift]  # perhaps it is a slicing O(n) copy overhead 

print("\nafter namestofilter:")
print("newarr: {}".format(newarr))
print("origarr: {}".format(origarr))

输出:

origarr: [{'name': 'test01', 'type': 0, 'value': 42}, {'name': 'test02', 'type': 0, 'value': 142}, {'name': 'test03', 'type': 2, 'value': 242}, {'name': 'test04', 'type': 2, 'value': 342}, {'name': 'test05', 'type': 3, 'value': 42}]

lastdictelem: {'name': 'test05', 'type': 3, 'value': 42}
after pop, origarr: [{'name': 'test01', 'type': 0, 'value': 42}, {'name': 'test02', 'type': 0, 'value': 142}, {'name': 'test03', 'type': 2, 'value': 242}, {'name': 'test04', 'type': 2, 'value': 342}]

after namestofilter:
newarr: [{'name': 'test01', 'type': 0, 'value': 42}, {'name': 'test02', 'type': 0, 'value': 142}]
origarr: [{'name': 'test03', 'type': 2, 'value': 242}, {'name': 'test04', 'type': 2, 'value': 342}]