简体   繁体   中英

Combining multiple lines within a list

I created a script which reads data from multiple files to generate a pattern. However, since I am trying to generate the pattern column-by-column, I decided to encode the entire data into a coordinate system.

Example:

[('0', 1), ('0', 2), ('0', 3), ('1', 4), ('2', 5), ('3', 6), ('3', 7), ('3', 8), ('2', 9), ('1', 10), ('0', 11), ('-1', 12), ('-2', 13), ('-3', 14), ('-3', 15), ('-3', 16), ('-2', 17), ('-1', 18), ('0', 19), ('0', 20), ('0', 21)]

Afterwards, depending on the size of the pattern I took the coordinates and converted it into a pattern:

['0\t*', '0\t *', '0\t  *', '1\t   *', '2\t    *', '3\t     *', '3\t      *', '3\t       *', '2\t        *', '1\t         *', '0\t          *', '-1\t           *', '-2\t            *']

Okay. So, now my issues is that I want to combine the 'strings' that start with the same coordinate.

So basically, the value at 0 would become a combination of the four strings that start with 0.

0\t***       *

The value at 1 would be a combination of the two strings that start with 1, and so forth.

Can someone please help me or guide me into the right direction. I don't know how to cycle through the list and combine the strings into their respective pattern for every line.

One way to do it is to convert them to binary and map to string you need.

data = [('0', 1), ('0', 2), ('0', 3), ('1', 4), ('2', 5), ('3', 6), ('3', 7), ('3', 8), ('2', 9), ('1', 10), ('0', 11), ('-1', 12), ('-2', 13), ('-3', 14), ('-3', 15), ('-3', 16), ('-2', 17), ('-1', 18), ('0', 19), ('0', 20), ('0', 21)]


output = {}

for (k,v) in data:
    if k not in output:
        output[k] = 0
    output[k] = 2**v | output[k]  # map to binary space.

for k in output:
    tmp = bin(output[k])[2:][::-1]   #cut binary prefix and reverse it.
    stared = tmp.replace('1', '*').replace('0',' ')
    print('%s\t%s' % (k,stared))

Result:

0        ***       *       ***
1           *     *
2            *   *
3             ***
-1                  *     *
-2                   *   *
-3                    ***

Explain:

Ok. The first for-loop. Basically, I changed each number to a power of two. I did that because of the property of binary string can be used to represent each position of '*' or ' '.

('0',1) --> ('0',2)     # 01
('0',2) --> ('0',4)     # 001
('0',3) --> ('0',8)     # 0001
('1',4) --> ('1',16)    
...
so on

Now observe that if we combine 01, 001, 0001 using logical 'or'( | ) operator we will get pretty much ('0', 0111) as a result.

The raw result of the first loop will be:

{'0': 3672078, '1': 1040, '2': 544, '3': 448, '-1': 266240, '-2': 139264, '-3': 114688}

The numbers are pretty scary but don't let a representation fool you. It arranges nice and meaningful under the binary form. eg '0': 3672078 is '0': 0b1110000000100000001110 which matches what is needed(in reversed order).

The second loop is mere to convert that into a binary representation. bin is a python builtin function to turn decimal number to a binary string. eg bin(2) --> 0b01 . Now, we don't need the 0b prefix so we cut it by [:2] operator. It will returns string skipped first two chars. After that, [::-1] operator has added to reverse the binary string because the original form has the most significant to the right(the bit with the highest value)

Then, in the last step, we replace '1' with '*' and '0' with ' ' and format it properly.

x = ['0\t*', '0\t *', '0\t  *', '1\t   *', '2\t    *', '3\t     *']
y = [i for i in x if i.startswith('0\t')]
y

['0\\t*', '0\\t *', '0\\t *']

Do you mean something like this above?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM