0

Ok, while I maybe wrong, I have the feeling I can solve this without the help of a function. With this kind of input list:

input=[[1,2,3],[4,5],[7],[5,4,6],[5,4]]

I want a resulting list where inner lists sharing a common element are concatenated:

result=[[1,2,3],[4,5,6],[7]]

I already found the

if any(x in result[j] for x in input[i])

syntax that seems helpful for my problem, but now I'm stuck.

[EDIT] one of my trials:

input=[[1,2,3],[4,5],[7],[5,4,6],[5,4]]

result=[input[0]]
for i in range(len(input)):
    for j in range(len(result)):
        if result[j] != input[i]:
            if any(x in result[j] for x in input[i]):
                result[j].extend(input[i])
                result[j]=list(set(result[j]))
                print "concatenate ",result[j], input[i]
                break
            else :
                result.append(input[i])
                print "append ", result[j], input[i]
                break
>>> (bad) result
[[1, 2, 3], [4, 5], [7], [5, 4, 6], [5, 4]]

While if I initialize result with result=[input[-1]] it works:

input=[[1,2,3],[4,5],[7],[5,4,6],[5,4]]

result=[input[-1]]
for i in range(len(input)):
    for j in range(len(result)):
        if result[j] != input[i]:
            if any(x in result[j] for x in input[i]):
                result[j].extend(input[i])
                result[j]=list(set(result[j]))
                print "concatenate ",result[j], input[i]
                break
            else :
                result.append(input[i])
                print "append ", result[j], input[i]
                break
>>> (good) result
[[4, 5, 6], [1, 2, 3], [7]]
yvecai
  • 31
  • 3
  • 1
    Welcome to Stack Overflow! It looks like you want us to write some code for you. While many users are willing to produce code for a coder in distress, they usually only help when the poster has already tried to solve the problem on their own. A good way to demonstrate this effort is to include the code you've written so far, example input (if there is any), the expected output, and the output you actually get (console output, stack traces, compiler errors - whatever is applicable). The more detail you provide, the more answers you are likely to receive. Check the [FAQ] and [ask] – Inbar Rose Nov 17 '13 at 09:27
  • Not sure exactly what you are trying to do, please supply more information on what you are attempting to do, as I mentioned above - sample input/output is greatly helpful in this case. – Inbar Rose Nov 17 '13 at 09:27
  • @InbarRose I think the output and input is already there.. – aIKid Nov 17 '13 at 09:30
  • I don't get what you're asking for. – roippi Nov 17 '13 at 09:34
  • Thanks, edited with non-working code – yvecai Nov 17 '13 at 09:37
  • 1
    @user1189129 I am still unable to understand what you are trying to do here. Can you add a small summary of what you want to achieve? – Anshul Goyal Nov 17 '13 at 09:40
  • possible duplicate of [Replace list of list with "condensed" list of list while maintaining order](http://stackoverflow.com/questions/13714755/replace-list-of-list-with-condensed-list-of-list-while-maintaining-order) – Blckknght Nov 17 '13 at 13:39
  • The possible duplicate I just linked to appears to be the same problem you're trying to solve here. It has a bunch of different solutions (including one from me) and some comparisons between them to see which perform best on different kinds of input (some inputs are very bad for some algorithms). – Blckknght Nov 17 '13 at 13:43
  • How long is your list? If it is not too long, you can do a trivial `O(n^2)` to test each pair for overlapping elements. – Thomas Ahle Feb 04 '14 at 21:51

2 Answers2

1

This is a more simple and well-performing approach to solve your problem:

def concat(myinput) :
    myinput_copy = [set(elem) for elem in myinput]
    result = []
    i = 0

    # use `while` to avoid `for` problems (you're deleting list elems)
    while i < len(myinput_copy) :
        result.append(myinput_copy[i])
        j = i + 1
        while j < len(myinput_copy) :
            if result[i] & myinput_copy[j] :
                result[i] |= myinput_copy[j]
                del myinput_copy[j]
                j = i + 1
            else :
                j += 1
        i += 1

    return result

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

It's about two times faster than J.F. Sebastian's answer to the other question, even if the other question wanted a different sorting.

I used myinput because input is a built-in function, and it's better to not masque it.

About sets and their operators: http://docs.python.org/3/tutorial/datastructures.html#sets (Python 3)

By the way, your solution is wrong, user1189129. Try your code with this input to see the problem: input = [[1, 2, 3], [1, 8], [1, 9], [4, 5], [7], [5, 4, 6], [5, 4]]

Community
  • 1
  • 1
Marco Sulla
  • 15,299
  • 14
  • 65
  • 100
0

You can convert your list to plain list (extract all variables from sublist into a bigger list) and then split them into the chunks:

def chunks(l, n):
    for i in xrange(0, len(l), n):
        yield l[i:i+n]

def plain(lst):
    return set([x for y in lst for x in y])

lst = [[1,2,3],[4,5],[7],[5,4,6],[5,4]]

print list(chunks(tuple(plain(l)), 3))
JadedTuna
  • 1,783
  • 2
  • 18
  • 32