insert element in a list after every 2 element - python

I have this code:
l = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
def add(l, n):
lret = l.copy()
i = n
while i <= len(lret):
lret.insert(i, 0.0)
i += (n+1)
return lret
lret = add(l,2)
print(lret)
Is a way to make the add() function a one-line function?

You can use zip() to build tuples that contain n elements from the original list with an added element, and then use chain.from_iterable() to flatten those tuples into the final list:
from itertools import repeat, chain
def add(lst, n):
return list(chain.from_iterable(zip(*(lst[s::n] for s in range(n)), repeat(0.0))))
This outputs:
[1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 5.0, 6.0, 0.0]

Possible solution if you want the whole block in one line:
return [x for y in (l[i:i + n] + [0.0] * (i < len(l) - n + 2) for
i in xrange(0, len(l), n)) for x in y]
Gives the same output
[1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 5.0, 6.0, 0.0]

Found another way to do it:
def add(l,n=2):
return [item for sublist in [(e,) if i % n == 0 or i == 0 else (e, 0.0) for i, e in enumerate(l)] for item in sublist]
[1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 5.0, 6.0, 0.0]

Related

How do I count the last elements in a list after a certain element?

I have a python list containing zeros and ones like this:
a = [1.0 1.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0]
I know how to count the ones and zeros in this, but what I can't manage to figure out is how to count the last zeros after the last 1.0 in that list. In this case the solution would be "2".
I would like to have a simple code which I can use for this problem in order to put it in a loop.
I hope someone can help me with that. Thank you!
Try this:
a = [1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0]
a[::-1].index(1)
You reverse the list, and take the index of the first 1.
An alternative using functional programming:
from itertools import takewhile
from operator import eq
from functools import partial
equal_0 = partial(eq, 0)
a = [1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0]
res = sum(1 for _ in takewhile(equal_0, reversed(a)))
print(res)
Output
2
Another solution, if you want to use explicit for-loop:
a = [1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0]
cnt = 0
for v in reversed(a):
if v:
break
cnt += 1
print(cnt)
Prints:
2

Is there a way to add list elements that is equal to a given number with higher elements

I am trying to add list elements that are closest or equal to 15
I am assuming 1st element from the list as total.
It should add in total with 3rd element from top to bottom.
If total > 15 then it should not add in total and go for the next loop.
I am trying the below code, could you suggest here what I am doing wrong -
list1 = [
[5.0, 1.3, 6.6, 5.076923076923077],
[9.0, 1.5, 7.0, 4.666666666666667],
[4.0, 1.0, 4.0, 4.0],
[3.0, 2.0, 5.5, 2.75],
[7.0, 1.6, 3.5, 2.1875],
[2.0, 1.7, 3.5, 2.058823529411765],
[1.0, 3.0, 6.0, 2.0],
[6.0, 1.0, 2.0, 2.0],
[8.0, 2.5, 5.0, 2.0],
[10.0, 1.8, 1.0, 0.5555555555555556]
]
income = 15
total = 0
for i in list1:
if not (total + i[1] > 15):
total += i[1]
print(total)
the output should be 14.9
The problem is that you use a break.
You have to check that adding the current
number in your loop will not result in the
total sum being more than 15.
income = 15
total = 0
for i in list1:
if not (total + i[1] > income):
total += i[1]
But this code will not always work. because number might come in different orders there might be an order were it adds up to exactly 15 but that's a bit more complicated.

List denies to be appended

Below is a portion of python code which is meant to work with FreeCAD libraries. I can provide the full code if requested.
What's weird in this code is that appending to a list, mr_fus.References, does no effect on the size of the list. I also tried to append to a dummy list, temp, and its size returned as expected.
Here is the definition of References.
Although type() indicates that References is a list, to me, it looks like no ordinary list. I am curious if it is possible for a list to deny to add element to itself.
temp = [] # just for comparison
for i in range(1,len(App.ActiveDocument.Shape004.Shape.Faces)):
mr_fus.References.append((App.ActiveDocument.Shape004.Shape, App.ActiveDocument.Shape004.Shape.Faces[i]))
temp.append((App.ActiveDocument.Shape004.Shape, App.ActiveDocument.Shape004.Shape.Faces[i]))
print(type(mr_fus.References)) # <class 'list'>
print(len(mr_fus.References)) # 0 # why??
print(len(temp)) # 18
EDIT: Here is a reproducible example though not minimal.
import sys
import math
import numpy
sys.path.append('/usr/lib/freecad/lib/')
import FreeCAD
import Draft
import Part
import BOPTools.JoinFeatures
doc = FreeCAD.newDocument('newdoc')
ZERO = 1e-10
def U(c, xl):
u = c[5]
if c[6] != 0:
t = c[0] + c[1] * abs((xl + c[2]) / c[3]) ** c[4]
if abs(t) <= ZERO:
t = 0
u += c[6] * t ** (1./c[7])
return u;
class Fuselage:
def H(xl):
if xl < 0.4:
c = [1.0, -1.0, -0.4, 0.4, 1.8, 0.0, 0.25, 1.8]
elif xl < 0.8:
c = [0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.0]
elif xl < 1.9:
c = [1.0, -1.0, -0.8, 1.1, 1.5, 0.05, 0.2, 0.6]
elif xl < 2.0:
c = [1.0, -1.0, -1.9, 0.1, 2.0, 0.0, 0.05, 2.0]
return U(c, xl);
def W(xl):
if xl < 0.4:
c = [1.0, -1.0, -0.4, 0.4, 2.0, 0.0, 0.25, 2.0]
elif xl < 0.8:
c = [0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.0]
elif xl < 1.9:
c = [1.0, -1.0, -0.8, 1.1, 1.5, 0.05, 0.2, 0.6]
elif xl < 2.0:
c = [1.0, -1.0, -1.9, 0.1, 2.0, 0.0, 0.05, 2.0]
return U(c, xl);
def Z(xl):
if xl < 0.4:
c = [1.0, -1.0, -0.4, 0.4, 1.8, -0.08, 0.08, 1.8]
elif xl < 0.8:
c = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
elif xl < 1.9:
c = [1.0, -1.0, -0.8, 1.1, 1.5, 0.04, -0.04, 0.6]
elif xl < 2.0:
c = [0.0, 0.0, 0.0, 0.0, 0.0, 0.04, 0.0, 0.0]
return U(c, xl);
def N(xl):
if xl < 0.4:
c = [2.0, 3.0, 0.0, 0.4, 1.0, 0.0, 1.0, 1.0]
elif xl < 0.8:
c = [0.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0]
elif xl < 1.9:
c = [5.0, -3.0, -0.8, 1.1, 1.0, 0.0, 1.0, 1.0]
elif xl < 2.0:
c = [2.0, 0.0, 0.0, 0.0, 0.0, 0.04, 1.0, 1.0]
return U(c, xl);
class Pylon:
def H(xl):
if xl < 0.8:
c = [1.0, -1.0, -0.8, 0.4, 3.0, 0.0, 0.145, 3.0]
elif xl < 1.018:
c = [1.0, -1.0, -0.8, 0.218, 2.0, 0.0, 0.145, 2.0]
return U(c, xl);
def W(xl):
if xl < 0.8:
c = [1.0, -1.0, -0.8, 0.4, 3.0, 0.0, 0.166, 3.0]
elif xl < 1.018:
c = [1.0, -1.0, -0.8, 0.218, 2.0, 0.0, 0.166, 2.0]
return U(c, xl);
def Z(xl):
if xl < 0.4:
c = [0.0, 0.0, 0.0, 0.0, 0.0, 0.125, 0.0, 0.0]
elif xl < 1.018:
c = [1.0, -1.0, -0.8, 1.1, 1.5, 0.065, 0.06, 0.6]
return U(c, xl);
def N(xl):
if xl < 0.4:
c = [0.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0]
elif xl < 1.018:
c = [0.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0]
return U(c, xl);
def yl(xl, phi, part):
return r(part.H(xl), part.W(xl), part.N(xl), phi) * math.sin(phi)
def zl(xl, phi, part):
return r(part.H(xl), part.W(xl), part.N(xl), phi) * math.cos(phi) + part.Z(xl)
def r(H, W, N, phi):
a = abs(0.5 * H * math.sin(phi)) ** N + abs(0.5 * W * math.cos(phi)) ** N
b = (0.25 * H * W) ** N
return (b / a) ** (1./N)
xm = numpy.linspace(0.00001, 2, 10)
xp = numpy.linspace(0.40001, 1.018, 10)
p = numpy.linspace(0, 2*math.pi, 10)
def makepart(part, x):
polygons = []
for i in range(len(x)-1):
points = []
for j in range(len(p)-1):
points.append(FreeCAD.Vector(x[i], yl(x[i], p[j], part), zl(x[i], p[j], part)))
points.append(points[0])
polygons.append(Part.makePolygon(points))
loft = Part.makeLoft(polygons)
cap1 = Part.Face(polygons[0])
cap2 = Part.Face(polygons[-1])
shell = Part.Shell(loft.Faces+[cap1, cap2])
Part.show(shell)
return shell
fuselage = makepart(Fuselage, xm)
pylon = makepart(Pylon, xp)
# join-connect fuselage and pylon
# let's call the joined object 'heli'
heli = BOPTools.JoinFeatures.makeConnect(name = 'Connected')
heli.Objects = [App.ActiveDocument.Shape, App.ActiveDocument.Shape001]
heli.Proxy.execute(heli)
heli.purgeTouched()
# make heli a solid
s = Part.Solid(Part.Shell(heli.Shape.Faces))
Part.show(s)
# make a sphere
sphere = Part.makeSphere(2,FreeCAD.Vector(1,0,0))
Part.show(sphere)
# cut heli from sphere
cut = sphere.cut(s)
Part.show(cut)
# extract seem of sphere
import CompoundTools.CompoundFilter
f = CompoundTools.CompoundFilter.makeCompoundFilter(name = 'CompoundFilter')
f.Base = App.ActiveDocument.Shape004
f.FilterType = 'window-volume'
f.Proxy.execute(f)
f.purgeTouched()
# make a line from seem of sphere to heli
line = Draft.makeWire([heli.Shape.Vertex27.Point, App.ActiveDocument.CompoundFilter.Shape.Vertex1.Point])
# split heli and line
import BOPTools.SplitFeatures
split = BOPTools.SplitFeatures.makeBooleanFragments(name= 'BooleanFragments')
split.Objects = [App.ActiveDocument.Shape004, App.ActiveDocument.Line]
split.Mode = 'Standard'
split.Proxy.execute(split)
split.purgeTouched()
#export to step
#split.Shape.exportStep("robin.step")
import ObjectsFem
mesh = ObjectsFem.makeMeshGmsh(FreeCAD.ActiveDocument, 'FEMMeshGmsh')
mesh.CharacteristicLengthMin = 0.5
mesh.CharacteristicLengthMax = 0.5
mesh.ElementDimension = 3
FreeCAD.ActiveDocument.ActiveObject.Part = FreeCAD.ActiveDocument.Shape004
mr_fus = ObjectsFem.makeMeshRegion(FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.FEMMeshGmsh, 0.5, 'fus')
mr_outer = ObjectsFem.makeMeshRegion(FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.FEMMeshGmsh, 1.0, 'outer')
mr_fus.CharacteristicLength = 0.7
temp = []
for i in range(1,len(App.ActiveDocument.Shape004.Shape.Faces)):
mr_fus.References.append((App.ActiveDocument.Shape004.Shape, App.ActiveDocument.Shape004.Shape.Faces[i]))
temp.append((App.ActiveDocument.Shape004.Shape, App.ActiveDocument.Shape004.Shape.Faces[i]))
print(type(mr_fus.References))
print(len(mr_fus.References))
print(len(temp))
EDIT: About FreeCAD version:
OS: Ubuntu 19.04
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.4.
Build type: Release
Python version: 3.7.3
Qt version: 5.12.2
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/United States (en_US)

Add values when there is a gap between elements

I have a list defined as
A = [1.0, 3.0, 6.0, 7.0, 8.0]
I am trying to fill the gap between the elements of the list with zero values. A gap is an increment between elements that is more than one. So for instance between 1.0 and 3.0 there is one gap: 2.0 and between 3.0 and 6.0 there are two gaps:4.0 and 5.0
I am working with this code but it is not complete and I am missing adding multiple values when the gap is bigger than one increment
B = []
cnt = 0
for i in range(len(A)-1):
if A[i] == A[i+1] - 1:
B.append(A[cnt])
cnt += 1
if A[i] != A[i+1] - 1:
B.append(A[cnt])
B.append(0.0)
cnt += 1
The output of this code is:
B = [1.0, 0.0, 3.0, 0.0, 6.0, 7.0]
But since there are two gaps between 3.0 and 6.0 I need B to look like this:
B = [1.0, 0.0, 3.0, 0.0, 0.0, 6.0, 7.0]
I am a bit stuck on how to do this and I already have a feeling that my code is not very optimized. Any help is appreciated!
You can use a list comprehension. Assuming your list is ordered, you can extract the first and last indices of A. We use set for O(1) lookup complexity within the comprehension.
A = [1.0, 3.0, 6.0, 7.0, 8.0]
A_set = set(A)
res = [i if i in A_set else 0 for i in range(int(A[0]), int(A[-1])+1)]
print(res)
[1, 0, 3, 0, 0, 6, 7, 8]
However, for larger arrays I'd recommend you use a specialist library such as NumPy:
import numpy as np
A = np.array([1.0, 3.0, 6.0, 7.0, 8.0]).astype(int)
B = np.zeros(A.max())
B[A-1] = A
print(B)
array([ 1., 0., 3., 0., 0., 6., 7., 8.])
Based on comments to the question, I can suggest the following solution:
B = [float(x) if x in A else 0.0 for x in range(int(min(A)), int(max(A)) + 1)]

Get to a dictionary format (by just saving non-zero values and indices) from a sparse matrixin in python [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 6 years ago.
Improve this question
I have a sparse matrix imagine something like following :
X=([1.5 0.0 0.0 71.9 0.0 0.0 0.0],
[0.0 10.0 0.0 2.0 0.0 0.0 0.0],
[0.0 0.0 0.0 0.0 0.0 0.0 11.0])
is there any specific method already existed which can convert such matrix into the following file format(or matrix), where each row only contain nonzero values and their corresponding indices of rows in X:
Example
X1=( 0:1.5 3:71.9
1:10 3:2
6:11 )
my question is is there any existed way which can produce such dictionary out of a sparse matrix in python ?
You could use a scipy.sparse.csr_matrix. It contains the data you are looking for in its indptr, indices and data attributes:
import scipy.sparse as sparse
X = sparse.csr_matrix([[1.5, 0.0, 0.0, 71.9, 0.0, 0.0, 0.0],
[0.0, 10.0, 0.0, 2.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 11.0]])
for row in range(X.shape[0]):
sl = slice(X.indptr[row], X.indptr[row+1])
pairs = zip(X.indices[sl], X.data[sl])
print(' '.join(['{}:{}'.format(idx, val) for idx, val in pairs]))
yields
0:1.5 3:71.9
1:10.0 3:2.0
6:11.0
Because you have a matrix of rows and columns, in my humble opinion, I think you need to mention the row and column of non-zero values for ease reference later, this can be done without importing any libraries:
>>> x
[[1.5, 0.0, 0.0, 71.9, 0.0, 0.0, 0.0], [0.0, 10.0, 0.0, 2.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 11.0]]
>>>
>>> l = []
>>>
>>> for i,subl in enumerate(x):
for j, item in enumerate(subl):
if item:
l.append(([i,j],item))
>>> l
[([0, 0], 1.5), ([0, 3], 71.9), ([1, 1], 10.0), ([1, 3], 2.0), ([2, 6], 11.0)]
This should get you a long way there:
X = np.array(
[[1.5, 0.0, 0.0, 71.9, 0.0, 0.0, 0.0],
[0.0, 10.0, 0.0, 2.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 11.0]])
>>> zip(np.argwhere(X).tolist(), X[X != 0])
[([0, 0], 1.5),
([0, 3], 71.900000000000006),
([1, 1], 10.0),
([1, 3], 2.0),
([2, 6], 11.0)]
You can also use a nested dictionary comprehension:
>>> {(row, col): val
for row, data in enumerate(X)
for col, val in enumerate(data)
if val != 0}
{(0, 0): 1.5,
(0, 3): 71.900000000000006,
(1, 1): 10.0,
(1, 3): 2.0,
(2, 6): 11.0}

Categories