Me pregunto si hay un atajo para hacer una lista simple de una lista de listas en Python.

Puedo hacer eso en un bucle for, pero ¿tal vez hay algún "one-liner" genial? Lo probé con reduce(), pero recibo un error.

Código

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)

Mensaje de error

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'
3167
Emma 5 jun. 2009 a las 00:30

29 respuestas

La mejor respuesta

Dada una lista de listas l,

flat_list = [item for sublist in l for item in sublist]

Lo que significa:

flat_list = []
for sublist in l:
    for item in sublist:
        flat_list.append(item)

Es más rápido que los accesos directos publicados hasta ahora. (l es la lista para aplanar).

Aquí está la función correspondiente:

flatten = lambda l: [item for sublist in l for item in sublist]

Como evidencia, puede usar el módulo timeit en la biblioteca estándar:

$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop

Explicación: los accesos directos basados en + (incluido el uso implícito en sum) son, necesariamente, O(L**2) cuando hay sublistas L, ya que la lista de resultados intermedios se alarga cada vez más en cada paso se asigna un nuevo objeto de la lista de resultados intermedios y se deben copiar todos los elementos del resultado intermedio anterior (así como algunos nuevos agregados al final). Entonces, por simplicidad y sin pérdida real de generalidad, digamos que tiene L sublistas de ítems I cada uno: los primeros ítems I se copian una y otra vez L-1 veces, los segundos I ítems L-2 veces, y así sucesivamente; el número total de copias es I multiplicado por la suma de x para x de 1 a L excluido, es decir, I * (L**2)/2.

La comprensión de la lista solo genera una lista, una vez, y copia cada elemento (desde su lugar de residencia original a la lista de resultados) también exactamente una vez.

4490
user1854182 29 mar. 2019 a las 10:29

La razón por la que su función no funcionó es porque extender extiende una matriz in situ y no la devuelve. Todavía puede devolver x de lambda, usando algo como esto:

reduce(lambda x,y: x.extend(y) or x, l)

Nota: extender es más eficiente que + en las listas.

22
Shannon Kelly 19 nov. 2019 a las 16:26

Versión recursiva

x = [1,2,[3,4],[5,[6,[7]]],8,9,[10]]

def flatten_list(k):
    result = list()
    for i in k:
        if isinstance(i,list):

            #The isinstance() function checks if the object (first argument) is an 
            #instance or subclass of classinfo class (second argument)

            result.extend(flatten_list(i)) #Recursive call
        else:
            result.append(i)
    return result

flatten_list(x)
#result = [1,2,3,4,5,6,7,8,9,10]
15
Saurabh Singh 14 dic. 2018 a las 10:51

matplotlib.cbook.flatten() funcionará para listas anidadas incluso si anidan más profundamente que en el ejemplo.

import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print list(matplotlib.cbook.flatten(l2))

Resultado:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

Esto es 18 veces más rápido que el subrayado ._. Flatten:

Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636
15
EL_DON 20 jul. 2018 a las 18:16

Considere instalar el paquete more_itertools.

> pip install more_itertools

Se envía con una implementación para flatten (fuente, de recetas de itertools):

import more_itertools


lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.flatten(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

A partir de la versión 2.4, puede aplanar iterables anidados más complicados con { {X0}} ( fuente , aportado por abarnet).

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.collapse(lst)) 
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

lst = [[1, 2, 3], [[4, 5, 6]], [[[7]]], 8, 9]              # complex nesting
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
26
pylang 13 jul. 2018 a las 21:06

Retiro mi declaración. sum no es el ganador. Aunque es más rápido cuando la lista es pequeña. Pero el rendimiento se degrada significativamente con listas más grandes.

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10000'
    ).timeit(100)
2.0440959930419922

¡La versión de suma todavía se está ejecutando durante más de un minuto y aún no se ha procesado!

Para listas medianas:

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
20.126545906066895
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
22.242258071899414
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
16.449732065200806

Usando pequeñas listas y timeit: number = 1000000

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
2.4598159790039062
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.5289170742034912
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.0598428249359131
38
devsaw 23 dic. 2013 a las 09:14

¿Por qué usas extender?

reduce(lambda x, y: x+y, l)

Esto debería funcionar bien.

32
MERose 31 dic. 2014 a las 12:07

Probé la mayoría de las soluciones sugeridas con perfplot (un proyecto favorito mío, esencialmente un envoltorio alrededor de timeit ), y encontrado

functools.reduce(operator.iconcat, a, [])

Ser la solución más rápida. (operator.iadd es igual de rápido).

enter image description here


Código para reproducir la trama:

import functools
import itertools
import numpy
import operator
import perfplot


def forfor(a):
    return [item for sublist in a for item in sublist]


def sum_brackets(a):
    return sum(a, [])


def functools_reduce(a):
    return functools.reduce(operator.concat, a)


def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def numpy_concatenate(a):
    return list(numpy.concatenate(a))


perfplot.show(
    setup=lambda n: [list(range(10))] * n,
    kernels=[
        forfor, sum_brackets, functools_reduce, functools_reduce_iconcat,
        itertools_chain, numpy_flat, numpy_concatenate
        ],
    n_range=[2**k for k in range(16)],
    xlabel='num lists'
    )
399
Nico Schlömer 5 dic. 2019 a las 12:21

Nota del autor : Esto es ineficiente. Pero divertido, porque monoides son increíbles. No es apropiado para la producción de código Python.

>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Esto solo suma los elementos de iterable pasados en el primer argumento, tratando el segundo argumento como el valor inicial de la suma (si no se proporciona, se usa 0 en su lugar y este caso le dará un error).

Debido a que está sumando listas anidadas, en realidad obtiene [1,3]+[2,4] como resultado de sum([[1,3],[2,4]],[]), que es igual a [1,3,2,4].

Tenga en cuenta que solo funciona en listas de listas. Para las listas de listas de listas, necesitará otra solución.

856
jorijnsmit 29 dic. 2018 a las 16:00

También se puede usar flat de NumPy:

import numpy as np
list(np.array(l).flat)

Edición 11/02/2016: solo funciona cuando las sublistas tienen dimensiones idénticas.

9
mdh 2 nov. 2016 a las 09:59

Lo siguiente me parece más simple:

>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print (np.concatenate(l))
[1 2 3 4 5 6 7 8 9]
11
devil in the detail 5 jul. 2017 a las 05:14

Si está dispuesto a renunciar a una pequeña cantidad de velocidad para una apariencia más limpia, entonces puede usar numpy.concatenate().tolist() o numpy.concatenate().ravel().tolist():

import numpy

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99

%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop

%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop

%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop

Puede encontrar más información aquí en los documentos numpy.concatenate y numpy.ravel

5
mkultra 27 oct. 2016 a las 03:31

¡Parece haber una confusión con operator.add! Cuando agrega dos listas juntas, el término correcto para eso es concat, no agregar. operator.concat es lo que necesitas usar.

Si está pensando en funcional, es tan fácil como esto ::

>>> from functools import reduce
>>> list2d = ((1, 2, 3), (4, 5, 6), (7,), (8, 9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)

Verá reducir respeta el tipo de secuencia, por lo que cuando proporciona una tupla, obtiene una tupla. Probemos con una lista ::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Ajá, recuperas una lista.

¿Qué hay de rendimiento ::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop

¡from_iterable es bastante rápido! Pero no es una comparación reducir con concat.

>>> list2d = ((1, 2, 3),(4, 5, 6), (7,), (8, 9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop
36
TrebledJ 9 may. 2019 a las 04:33
from nltk import flatten

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
flatten(l)

La ventaja de esta solución sobre la mayoría de las demás aquí es que si tiene una lista como:

l = [1, [2, 3], [4, 5, 6], [7], [8, 9]]

Mientras que la mayoría de las otras soluciones arrojan un error, esta solución las maneja.

5
Alijy 30 sep. 2019 a las 10:49

Puede que esta no sea la forma más eficiente, pero pensé en poner una línea (en realidad una de dos líneas). Ambas versiones funcionarán en listas anidadas de jerarquía arbitraria y explotan las características del lenguaje (Python3.5) y la recursividad.

def make_list_flat (l):
    flist = []
    flist.extend ([l]) if (type (l) is not list) else [flist.extend (make_list_flat (e)) for e in l]
    return flist

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = make_list_flat(a)
print (flist)

La salida es

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

Esto funciona en profundidad de primera manera. La recursividad disminuye hasta que encuentra un elemento que no es de la lista, luego extiende la variable local flist y luego la revierte al padre. Cada vez que se devuelve flist, se extiende al flist del padre en la comprensión de la lista. Por lo tanto, en la raíz, se devuelve una lista plana.

El anterior crea varias listas locales y las devuelve, que se utilizan para ampliar la lista de los padres. Creo que la solución para esto puede ser crear un gloabl flist, como a continuación.

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = []
def make_list_flat (l):
    flist.extend ([l]) if (type (l) is not list) else [make_list_flat (e) for e in l]

make_list_flat(a)
print (flist)

La salida es de nuevo

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

Aunque no estoy seguro en este momento sobre la eficiencia.

4
phoxis 20 may. 2018 a las 08:47

Otra forma divertida de hacer esto:

from functools import reduce
from operator import add

li=[[1,2],[3,4]]
x= reduce(add, li)
5
sudeepgupta90 28 ago. 2019 a las 08:09
def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])
6
englealuze 8 ago. 2017 a las 14:59

Puedes usar numpy:
flat_list = list(np.concatenate(list_of_list))

6
A. Attia 24 jul. 2018 a las 09:11
def flatten(l, a):
    for i in l:
        if isinstance(i, list):
            flatten(i, a)
        else:
            a.append(i)
    return a

print(flatten([[[1, [1,1, [3, [4,5,]]]], 2, 3], [4, 5],6], []))

# [1, 1, 1, 3, 4, 5, 2, 3, 4, 5, 6]
17
Guillaume Jacquenot 28 nov. 2016 a las 08:48

Puede usar itertools.chain():

>>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))

O puede usar itertools.chain.from_iterable() que no requiere desempaquetar la lista con el operador *:

>>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))

Este enfoque es posiblemente más legible que [item for sublist in l for item in sublist] y parece ser también más rápido:

$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
20000 loops, best of 5: 10.8 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 5: 21.7 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 5: 258 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;from functools import reduce' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 5: 292 usec per loop
$ python3 --version
Python 3.7.5rc1
1475
Boris 24 nov. 2019 a las 23:53

La solución más rápida que he encontrado (para una lista grande de todos modos):

import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()

¡Hecho! Por supuesto, puede volver a convertirlo en una lista ejecutando list (l)

4
Canuck 28 nov. 2016 a las 21:09

La respuesta aceptada no funcionó para mí cuando trataba con listas basadas en texto de longitudes variables. Aquí hay un enfoque alternativo que funcionó para mí.

l = ['aaa', 'bb', 'cccccc', ['xx', 'yyyyyyy']]

Respuesta aceptada que no funcionó:

flat_list = [item for sublist in l for item in sublist]
print(flat_list)
['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'xx', 'yyyyyyy']

Nueva solución propuesta que funcionó para mí:

flat_list = []
_ = [flat_list.extend(item) if isinstance(item, list) else flat_list.append(item) for item in l if item]
print(flat_list)
['aaa', 'bb', 'cccccc', 'xx', 'yyyyyyy']
14
user9074332 12 oct. 2018 a las 01:32

Una mala característica de la función anterior de Anil es que requiere que el usuario especifique siempre manualmente el segundo argumento para que sea una lista vacía []. Esto debería ser un valor predeterminado. Debido a la forma en que funcionan los objetos de Python, estos deben establecerse dentro de la función, no en los argumentos.

Aquí hay una función de trabajo:

def list_flatten(l, a=None):
    #check a
    if a is None:
        #initialize with empty list
        a = []

    for i in l:
        if isinstance(i, list):
            list_flatten(i, a)
        else:
            a.append(i)
    return a

Pruebas:

In [2]: lst = [1, 2, [3], [[4]],[5,[6]]]

In [3]: lst
Out[3]: [1, 2, [3], [[4]], [5, [6]]]

In [11]: list_flatten(lst)
Out[11]: [1, 2, 3, 4, 5, 6]
13
Deleet 29 nov. 2016 a las 03:45

No reinvente la rueda si está utilizando Django :

>>> from django.contrib.admin.utils import flatten
>>> l = [[1,2,3], [4,5], [6]]
>>> flatten(l)
>>> [1, 2, 3, 4, 5, 6]

... Pandas :

>>> from pandas.core.common import flatten
>>> list(flatten(l))

... Itertools :

>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))

... Matplotlib

>>> from matplotlib.cbook import flatten
>>> list(flatten(l))

... Unipath :

>>> from unipath.path import flatten
>>> list(flatten(l))

... Herramientas de configuración :

>>> from setuptools.namespaces import flatten
>>> list(flatten(l))
64
Max Malysh 2 ago. 2019 a las 19:30

Si desea aplanar una estructura de datos donde no sabe qué tan profundo está anidado, puede usar iteration_utilities.deepflatten 1

>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Es un generador, por lo que debe convertir el resultado en un list o iterarlo explícitamente.


Para aplanar solo un nivel y si cada uno de los elementos es iterable, también puede usar iteration_utilities.flatten, que en sí mismo es una envoltura delgada alrededor de itertools.chain.from_iterable:

>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Solo para agregar algunos tiempos (basados en la respuesta de Nico Schlömer que no incluyó la función presentada en esta respuesta):

enter image description here

Es un diagrama log-log para acomodar la gran variedad de valores abarcados. Para razonamiento cualitativo: más bajo es mejor.

Los resultados muestran que si el iterable contiene solo unos pocos iterables internos, entonces sum será más rápido, sin embargo, para iterables largos solo el itertools.chain.from_iterable, iteration_utilities.deepflatten o la comprensión anidada tienen un rendimiento razonable con {{ X3}} es el más rápido (como ya notó Nico Schlömer).

from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
    return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
    return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
    return sum(lsts, [])

def reduce_add(lsts):
    return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
    return list(flatten(lsts))

def flatten(items):
    """Yield items from any nested iterable; see REF."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            yield from flatten(x)
        else:
            yield x

def reduce_concat(lsts):
    return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
    return list(deepflatten(lsts, depth=1))


from simple_benchmark import benchmark

b = benchmark(
    [nested_list_comprehension, itertools_chain_from_iterable, pythons_sum, reduce_add,
     pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
    arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
    argument_name='number of inner lists'
)

b.plot()

1 Descargo de responsabilidad: Soy la autora de esa biblioteca

44
MSeifert 18 abr. 2018 a las 21:27
from functools import reduce #python 3

>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(lambda x,y: x+y,l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

El método extend() en su ejemplo modifica x en lugar de devolver un valor útil (que reduce() espera).

Una forma más rápida de hacer la versión reduce sería

>>> import operator
>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(operator.concat, l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
172
Sanjay Verma 2 ene. 2018 a las 05:02

Código simple para underscore.py paquete del ventilador

from underscore import _
_.flatten([[1, 2, 3], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Resuelve todos los problemas de aplanamiento (ninguno de los elementos de la lista o anidamiento complejo)

from underscore import _
# 1 is none list item
# [2, [3]] is complex nesting
_.flatten([1, [2, [3]], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Puede instalar underscore.py con pip

pip install underscore.py
5
Vu Anh 25 mar. 2017 a las 05:09
flat_list = []
for i in list_of_list:
    flat_list+=i

Este código también funciona bien, ya que solo extiende la lista por completo. Aunque es muy similar, solo tiene uno para el bucle. Por lo tanto, tiene menos complejidad que agregar 2 para bucles.

5
Deepak Yadav 20 jun. 2018 a las 11:12

Otro enfoque inusual que funciona para listas heterogéneas y homogéneas de enteros:

from typing import List


def flatten(l: list) -> List[int]:
    """Flatten an arbitrary deep nested list of lists of integers.

    Examples:
        >>> flatten([1, 2, [1, [10]]])
        [1, 2, 1, 10]

    Args:
        l: Union[l, Union[int, List[int]]

    Returns:
        Flatted list of integer
    """
    return [int(i.strip('[ ]')) for i in str(l).split(',')]
4
tharndt 13 sep. 2018 a las 11:34
952914