I reformulate my wish for a function - call it my_collect2(expr, fact) - more precisely:
Assume expr is a sum of products. Each factor in each product can be a constant, a single variable or any other expression like a+b, xy, sin(axy), ... If the sum contains also a single variable (rather than a product), I consider this variable also as "product", e.g. in (a+b)x + x the last x shall also be considered as "product" and so this whole expression is a sum of products. For this expression
my_collect2((a+b)*x + x, x)
shall yield
(a+b+1) * x
Generally assume that fact is also any expression. If fact occures as common factor in two or more of the products, fact should be factored out by the call my_collect2(expr, fact).
Now assume expr is not a sum of products, but when seeing expr as a tree, there may be one or more sums of products inside. Then the factoring-out shall also be applied recursively to each 'inner' sum of products.
More generally, the recursion shall also be made for a python list of expressions, i.e. each expression in the list shall be searched for possible factoring-out's.
Apart from factoring out I do not want to apply any mathemetical rearrangements of the expression (that keep the expression value unchanged). With this I mean e.g. if you have
var('a b c x y z')
my_collect2( (a+b)*(x+y-1) + a+b + 2*c*(x+y) , x*y)
I do not want to get
(a+b+2*c) * (x+y)
since this would first require to rearrange the expression to (a+b)(x+y) + 2c*(x+y) and then factor out (x+y).
Further more, my_collect2 should also be callable with three arguments:
my_collect2(expr, fact, subs_fact)
should work like my_collect2(expr, fact) except that the each factored out term fact should be substituted by subs_fact, e.g.
sage: var('x1 y1 y2 y3 z1 z2 x1y1')
sage: mycollect2(x1*y1*y2 + y3*x1*y1, x1*y1, x1y1)
Expected: (y2 + y3) * x1y1
It should be possible to write such a function my_collect2(), but since I'm new to sage it will probably be easier to do for someone with more experience.
My idea is to recursively scan the expression tree for sums of products and then look if fact is a common factor of at least two of the products.
I give some examples:
sage: var('x1 y1 y2 y3 z1 z2')
sage: my_collect2(x1*y1*y2 + y3*x1*y1, x1*y1)
Expected: (y2 + y3) * x1*y1
sage: var('x1 y1 y2 y3 z1')
sage: my_collect2(sin(exp( (x1+cos(y1))*z1*y2 + y3*(x1+cos(y1))*z1 )), (x1+cos(y1))*z1)
Expected: sin(exp( (y2 + y3) * (x1+cos(y1))*z1 ))
sage: my_collect2([z1*(x1+y1) + z2*(x1+y1), (z1-1)*(x1+y1) + x1 + y1 + z2*(x1+y1)], x1+y1)
Expected: [(z1 + z2)*(x1+y1), (z1-1)*(x1+y1) + x1 + y1 + z2*(x1+y1)]