我需要将SQL的结果转换为分层的dict。我创建类DictMaker并编写单个测试。但是测试的运行在某些时候失败或成功。我不明白这种行为。在课堂上没有随机的电话。
import unittest
class DictMaker:
def __init__( self, input_ ):
self._input = input_
self._dict = { }
def dict( self ):
self._make( )
return self._dict
def _make( self ):
for item in self._input:
for long_key, val in item.items( ):
self._add_leaf_value( long_key, val )
def _add_leaf_value( self, long_key, val ):
last = self._get_last_item( long_key )
leaf = self._get_leaf_key( long_key )
if leaf in last:
if last[ leaf ] != val:
list_ = self._get_last_list( long_key )
key = self._get_leaf_key( long_key )
list_.append( { key: val } )
else:
last[ leaf ] = val
def _get_leaf_key( self, long_key ):
return long_key.split( '.' )[ -1 ]
def _get_last_item( self, long_key ):
keys = long_key.split( '.' )[ :-1 ]
parent_dict = self._dict
parent_list = None
for key in keys:
if key in parent_dict:
parent_list = parent_dict[ key ]
parent_dict = parent_list[ -1 ]
else:
sub_dict = { }
parent_list = [ sub_dict ]
parent_dict[ key ] = parent_list
parent_dict = sub_dict
return parent_list[ -1 ]
def _get_last_list( self, long_key ):
keys = long_key.split( '.' )[ :-1 ]
parent_dict = self._dict
parent_list = None
for key in keys:
if key in parent_dict:
parent_list = parent_dict[ key ]
parent_dict = parent_list[ -1 ]
else:
sub_dict = { }
parent_list = [ sub_dict ]
parent_dict[ key ] = parent_list
parent_dict = sub_dict
return parent_list
class MyTestCase( unittest.TestCase ):
def test_run( self ):
input_ = [
{
'categories.id': 1,
'categories.label': 'Computers',
'categories.groups.id': 18,
'categories.groups.label': 'Servers and Servers equipment',
'categories.groups.names.id': 48,
'categories.groups.names.label': 'HP Memory'
},
{
'categories.id': 1,
'categories.label': 'Computers',
'categories.groups.id': 18,
'categories.groups.label': 'Servers and Servers equipment',
'categories.groups.names.id': 73,
'categories.groups.names.label': 'HP Options for servers'
},
{
'categories.id': 1,
'categories.label': 'Computers',
'categories.groups.id': 84,
'categories.groups.label': 'Tablets',
'categories.groups.names.id': 310,
'categories.groups.names.label': 'Tablets Samsung'
},
{
'categories.id': 1,
'categories.label': 'Computers',
'categories.groups.id': 84,
'categories.groups.label': 'Tablets',
'categories.groups.names.id': 313,
'categories.groups.names.label': 'Tablets Sony'
},
{
'categories.id': 2,
'categories.label': 'Periphery',
'categories.groups.id': 55,
'categories.groups.label': 'Loundspeakers',
'categories.groups.names.id': 330,
'categories.groups.names.label': 'Loundspeakers Ritmix'
},
{
'categories.id': 2,
'categories.label': 'Periphery',
'categories.groups.id': 55,
'categories.groups.label': 'Loundspeakers',
'categories.groups.names.id': 402,
'categories.groups.names.label': 'Loundspeakers MICROLAB'
},
{
'categories.id': 2,
'categories.label': 'Periphery',
'categories.groups.id': 58,
'categories.groups.label': 'Keyboards, mouses',
'categories.groups.names.id': 25,
'categories.groups.names.label': 'mouses G-Cube'
},
{
'categories.id': 2,
'categories.label': 'Periphery',
'categories.groups.id': 58,
'categories.groups.label': 'Keyboards, mouses',
'categories.groups.names.id': 27,
'categories.groups.names.label': 'Keyboards BTC '
},
]
expected = {
'categories': [
{
'id': 1,
'label': 'Computers',
'groups': [
{
'id': 18,
'label': 'Servers and Servers equipment',
'names': [
{
'id': 48,
'label': 'HP Memory'
},
{
'id': 73,
'label': 'HP Options for servers'
}
]
},
{
'id': 84,
'label': 'Tablets',
'names': [
{
'id': 310,
'label': 'Tablets Samsung'
},
{
'id': 313,
'label': 'Tablets Sony'
}
]
}
]
},
{
'id': 2,
'label': 'Periphery',
'groups': [
{
'id': 55,
'label': 'Loundspeakers',
'names': [
{
'id': 330,
'label': 'Loundspeakers Ritmix'
},
{
'id': 402,
'label': 'Loundspeakers MICROLAB'
}
]
},
{
'id': 58,
'label': 'Keyboards, mouses',
'names': [
{
'id': 25,
'label': 'mouses G-Cube'
},
{
'id': 27,
'label': 'Keyboards BTC '
}
]
}
]
}
]
}
maker = DictMaker( input_ )
actual = maker.dict( )
self.assertEqual( actual, expected )
if __name__ == '__main__':
unittest.main( )
在网上它工作正常(可能是由于Pypy)。但是本地运行很奇怪。 python(3.4.3)
答案 0 :(得分:0)
FIX。这是由于dict键在迭代时未定义。 解决问题添加力排序。
def _make( self ):
for item in self._input:
for long_key, val in item.items( ):
self._add_leaf_value( long_key, val )
更改为
def _make( self ):
for item in self._input:
items = list( item.items( ) )
items.sort( key=lambda t: len( t[ 0 ] ) )
for long_key, val in items:
self._add_leaf_value( long_key, val )