HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMajor

Reduce number of operations to get one array value

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
numberoperationsarrayvalueonereduceget

Problem

I can't wrap my head around that. There seem to be a lot of redundancy, and even if it is not called called more than ten times in the main loop, I still find it hard to swallow that it loops through the whole list at each invocation.

def get_file_info(f, stream, field):

    discoverer = GstPbutils.Discoverer()
    discoverer.connect('discovered', on_discovered)
    info = discoverer.discover_uri(f)

    for vinfo in info.get_video_streams():
        ftype = (vinfo.get_stream_type_nick())
        width = vinfo.get_width()
        height = (format(vinfo.get_height()))
        depth = (format(vinfo.get_depth()))
        framerate = ('Frate: {}'.format(vinfo.get_framerate_num()))
        bitrate = ('Brate: {}'.format(vinfo.get_max_bitrate()))
        par = vinfo.get_par_num()
        fname = vinfo.get_caps().to_string().split(',')[0]

    if stream == 'video':
        if field == 'duration':
            return str(convert_time(info.get_duration(), 'hh:mm:ss'))
        elif field == 'width':
            return str(width)
        elif field == 'height':
            return str(height)
        elif field == 'type':
            return str(ftype)
        elif field == 'depth':
            return str(depth)
        elif field == 'framerate':
            return str(framerate)
        elif field == 'bitrate':
            return str(bitrate)
        elif field == 'par':
            return str(par)
        elif field == 'name':
            return str(par)


I read the lambda documentation, but can't seem to write a proper one, but I would sure like to.

Solution

@Stewie Griffin's answer is good, but I dare say it promotes eval, where dict is safer and more expansive.

The main aim here is to use the same if's as Stewie, as they are definitely good.
As a dictionary contains things and you can't get other things out of it it's safer.
With Stiewies for example you can pass 'get_file_info' as the field and it'll give you ''.
It also means that you can return a dictionary for each and every stream in info.get_video_streams().

To obtain this we will make a variable video_info that will hold the needed information.

video_info = {
    'width': 2,
    'height': 3,
    'name': 'Name of video'
}

field = 'width'
str(video_info[field])
Out[3]: '2'

field = 'name'
str(video_info[field])
Out[5]: 'Name of video'


This means we just need to move all the information into this dictionary.
And so you'll need to change the for-loop to create a dictionary.

video_info = {
    'type': vinfo.get_stream_type_nick(),
    'width': vinfo.get_width(),
    'height': format(vinfo.get_height()),
    'depth': format(vinfo.get_depth()),
    'framerate': 'Frate: {}'.format(vinfo.get_framerate_num()),
    'bitrate': 'Brate: {}'.format(vinfo.get_max_bitrate()),
    'par': vinfo.get_par_num(),
    'fname': vinfo.get_caps().to_string().split(',')[0]
}


I'd also go on to say that you can change the code to return a dictionary and you can then remove all the field stuff from this function.
And you can use a list comprehension to return a dictionary for every info.get_video_streams().

which leads to:

def get_file_info(f, stream):
    discoverer = GstPbutils.Discoverer()
    discoverer.connect('discovered', on_discovered)
    info = discoverer.discover_uri(f)
    duration = convert_time(info.get_duration(), 'hh:mm:ss')
    return [
        {
            'duration': duration,
            'type': vinfo.get_stream_type_nick(),
            'width': vinfo.get_width(),
            'height': format(vinfo.get_height()),
            'depth': format(vinfo.get_depth()),
            'framerate': 'Frate: {}'.format(vinfo.get_framerate_num()),
            'bitrate': 'Brate: {}'.format(vinfo.get_max_bitrate()),
            'par': vinfo.get_par_num(),
            'fname': vinfo.get_caps().to_string().split(',')[0],
        }
        for vinfo in info.get_video_streams()
    ]

def get_file_field(f, stream, field):
    videos = get_file_info(f, stream)
    video_info = videos[-1]
    if stream == 'video':
        return str(video_info[field])

Code Snippets

video_info = {
    'width': 2,
    'height': 3,
    'name': 'Name of video'
}

field = 'width'
str(video_info[field])
Out[3]: '2'

field = 'name'
str(video_info[field])
Out[5]: 'Name of video'
video_info = {
    'type': vinfo.get_stream_type_nick(),
    'width': vinfo.get_width(),
    'height': format(vinfo.get_height()),
    'depth': format(vinfo.get_depth()),
    'framerate': 'Frate: {}'.format(vinfo.get_framerate_num()),
    'bitrate': 'Brate: {}'.format(vinfo.get_max_bitrate()),
    'par': vinfo.get_par_num(),
    'fname': vinfo.get_caps().to_string().split(',')[0]
}
def get_file_info(f, stream):
    discoverer = GstPbutils.Discoverer()
    discoverer.connect('discovered', on_discovered)
    info = discoverer.discover_uri(f)
    duration = convert_time(info.get_duration(), 'hh:mm:ss')
    return [
        {
            'duration': duration,
            'type': vinfo.get_stream_type_nick(),
            'width': vinfo.get_width(),
            'height': format(vinfo.get_height()),
            'depth': format(vinfo.get_depth()),
            'framerate': 'Frate: {}'.format(vinfo.get_framerate_num()),
            'bitrate': 'Brate: {}'.format(vinfo.get_max_bitrate()),
            'par': vinfo.get_par_num(),
            'fname': vinfo.get_caps().to_string().split(',')[0],
        }
        for vinfo in info.get_video_streams()
    ]

def get_file_field(f, stream, field):
    videos = get_file_info(f, stream)
    video_info = videos[-1]
    if stream == 'video':
        return str(video_info[field])

Context

StackExchange Code Review Q#133360, answer score: 22

Revisions (0)

No revisions yet.