I have a 2D list:
# # # ^ # ^ # ^
l = [['A', '1', '2'], ['B', 'xx', 'A'], ['C', 'B', 's'], ['D', 'd', 'B']]
and the first element in each list can be treated as an #ID string (in the example: A, B, C, D). Anywhere where the ID's (A, B, C, D) occur in the second dimension's lists I would like to replace it with the content of the actual list. Example: ['B', 'xx', 'A'] should become ['B', 'xx', ['A', '1', '2']] because A is an #ID (first string of list) and it occurs in the second list. Output should be:
n = [['A', '1', '2'], ['B', 'xx', ['A', '1', '2']], ['C', ['B', 'xx', ['A', '1', '2']], 's'],
['D', 'd', ['B', 'xx', ['A', '1', '2']]]]
The problem I am facing is that there can be longer lists and more branches so it's getting complicated. In the end I am trying to build a tree diagram. I was thinking of calculting first what is the highest branching but don't have a solution in mind yet.
l = [['A', '1', '2'], ['B', 'xx', 'A'], ['C', 'B', 's'], ['D', 'd', 'B']]
dic = {i[0]:i for i in l}
for i in l:
fv = i[0]
for j, v in enumerate(i):
if v in dic and j!=0:
dic[fv][j] = dic[v]
res = [v for i,v in dic.items()]
print(res)
output
[['A', '1', '2'],
['B', 'xx', ['A', '1', '2']],
['C', ['B', 'xx', ['A', '1', '2']], 's'],
['D', 'd', ['B', 'xx', ['A', '1', '2']]]]
Have you tried using a dictionary? If you have the ID's then you could possibly refer to them and then loop through the array and change entries. Below is what I had
l = [['A', '1', '2'], ['B', 'xx', 'A'], ['C', 'B', 's'], ['D', 'd', 'B'], ['E', 'C', 'b']]
dt = {}
for i in l:
dt[i[0]] = i
for i in range(len(l)):
for j in range(1, len(l[i])):
if(l[i][j] in dt):
l[i][j] = dt.get(l[i][j])
print(l)
Another more succinct version:
d = {item[0]: item for item in l}
for item in l:
item[1:] = [d.get(element, element) for element in item[1:]]
Related
my_list = ['A', 'B', 'C', 'D', 'E', 'B', 'F', 'D', 'C', 'B']
idx = my_list.index('B')
print("index :", idx)
In here I used the '.index()' function.
for i in my_list:
print(f"index no. {my_list.index(i)}")
I tried to find each index number of the items of the (my_list) list.
But it gave same result for same values. But they located in difference places of the list.
if 'B' == my_list[(len(my_list) - 1)]:
print("True")
if 'B' == my_list[(len(my_list) - 4)]:
print("True")
I need to mention particular values by the index number of their (to do something).
Imagine; I need to set values to nesting with the values of the list.
i.e :
my_list_2 = ['A', 'B', '2', 'C', '3', 'D', '4', 'E', 'B', '2', 'F', '6', 'D', 'C', '3', 'B']
- ------ ------ ------ - ------ ------ - ------ -
If I want to nesting values with their Consecutive (number type) items and
the other values need to nest with '*' mark (as default).Because they have no any Consecutive (numeric) values.
so then how I mention each (string) values and (numeric) values in a coding part to nesting them.
In this case as my example I expected result:
--> my_list_2 = [['A', ''], ['B', '2'], ['C', '3'], ['D', '4'], ['E', ''], ['B', '2'], ['F', '6'], ['D', ''], ['C', '3'], ['B', '']]
This is the coding part which I tried to do this :
def_setter = [
[my_list_2[i], '*'] if my_list_2[i].isalpha() and my_list_2[i + 1].isalpha() else [my_list_2[i], my_list_2[i + 1]]
for i in range(0, len(my_list_2) - 1)]
print("Result : ", def_setter)
But it not gave me the expected result.
Could you please help me to do this !
There might be a more pythonic way to reorganize this array, however, with the following function you can loop through the list and append [letter, value] if value is a number, append [letter, ''] if value is a letter.
def_setter = []
i = 0
while i < len(my_list_2):
if i + 1 == len(my_list_2):
if my_list_2[i].isalpha():
def_setter.append([my_list_2[i], ''])
break
prev, cur = my_list_2[i], my_list_2[i + 1]
if cur.isalpha():
def_setter.append([prev, ''])
i += 1
else:
def_setter.append([prev, cur])
i += 2
print(def_setter)
>>> [['A', ''],
['B', '2'],
['C', '3'],
['D', '4'],
['E', ''],
['B', '2'],
['F', '6'],
['D', ''],
['C', '3'],
['B', '']]
I am trying to re-order and extend lists of dictionary values with the right position and fill them with zeros.
myDict = {
"col-1": ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
"col-2": ['a', 'b', 'c', 'd', 'f', 'e']
}
The desired output should look like this:
myDict = {
"col-1": ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
"col-2": ['a', 'b', 'c', 'd', 'e', 'f', '0'] # '0' is zero
}
Note that values of lists are with order 'a', 'b', 'c', 'd', 'e', 'f', 'g'. The maximum list length in myDict.values() is fixed to 7 and the minimum is 6. myDict can have more than two elements.
I tried to use Python - extending and filling list with zeros to match another list but didn't know exactly how to make it work for my case.
Assuming the maximum length is 7 and values are only single characters from "a" to "g"
myDict = {
"col-1": ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
"col-2": ['a', 'b', 'c', 'd', 'e', 'f']
}
for key, value_list in myDict.items():
new_value_list = [0 for i in range(7)]
for value in value_list:
new_value_list[ord(value) - 97] = value
myDict[key] = new_value_list
print(myDict)
This should cover the cases identified in the original post and the clarification comment. The approach is, for each key of the dict, to iterate over the set of valid letters, outputting that letter (if it exists in the dict value), or '0' (if it doesn't).
myDict = {
"col-1": ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
"col-2": ['a', 'b', 'c', 'd', 'f', 'e'],
"col-3": ['a', 'c', 'f'],
"col-4": ['b', 'd']
}
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
for key, value in myDict.items():
myDict[key] = [(x if x in value else '0') for x in letters]
print(f"{key}: {myDict[key]}")
prints:
col-1: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
col-2: ['a', 'b', 'c', 'd', 'e', 'f', '0']
col-3: ['a', '0', 'c', '0', '0', 'f', '0']
col-4: ['0', 'b', '0', 'd', '0', '0', '0']
seems to me that you could do this with a for-while loop:
for key in myDict.keys():
myDict[key] = sorted(myDict[key])
while len(myDict[key])<len(myDict["column1"]):
myDict[key].append('0')
I have a list of numbers and values for each number. What I want to do is check if the number already exists in a dictionary and if it does, append the value to that list of values for the specific key.
For an Example
0
a
2
b
3
c
0
d
7
e
What I want to achieve is to populate a dictionary where the numbers would be the keys and letters would be the values.However in the event that the number 0 comes up again I want to take the value of the second 0 and append it to my list of values.
Basically the outcome would be
"0" : [a,d]
"2" : [b]
"3" : [c]
"7" : [e]
Right now im in the process of the following:
num_letter_dict = {}
num = ['0', '2', '3', '0','7']
letters = ['a', 'b', 'c', 'd','e']
for line in num:
if line in num_letter_dict:
num_letter_dict[line].append(letters)
else:
num_letter_dict[line] = [letters]
print(num_letter_dict)
This is the result I am getting
{'0': [['a', 'b', 'c', 'd', 'e']]}
{'0': [['a', 'b', 'c', 'd', 'e']], '2': [['a', 'b', 'c', 'd', 'e']]}
{'0': [['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']], '2': [['a', 'b', 'c', 'd', 'e']]}
{'0': [['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']], '2': [['a', 'b', 'c', 'd', 'e']], '3': [['a', 'b', 'c', 'd', 'e']]}
{'0': [['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']], '2': [['a', 'b', 'c', 'd', 'e']], '3': [['a', 'b', 'c', 'd', 'e']], '7': [['a', 'b', 'c', 'd', 'e']]}
You're appending letters, which by itself is a full list. Instead, you want to append the element in letter that corresponds to the index of the key you're looking at in the num list.
for idx, line in enumerate(num):
if line in num_letter_dict:
num_letter_dict[line].append(letters[idx]) # append the element
else:
num_letter_dict[line] = [letters[idx]]
Result:
>>> print(num_letter_dict)
{'0': ['a', 'c'], '2': ['b'], '3': ['d'], '7': ['e']}
You just need to append the individual letter to the relevant list inside the dictionary, and not the whole list of letters. The zip function will loop over corresponding values from the two input lists as shown:
num_letter_dict = {}
num = ['0', '2', '3', '0','7']
letters = ['a', 'b', 'c', 'd','e']
for n, letter in zip(num, letters):
if n not in num_letter_dict:
num_letter_dict[n] = []
num_letter_dict[n].append(letter)
print(num_letter_dict)
Gives:
{'0': ['a', 'c'], '3': ['d'], '7': ['e'], '2': ['b']}
I think this can help you.
num_letter_dict = {}
num = ['0', '2', '0', '3','7']
letters = ['a', 'b', 'c', 'd','e']
for value, line in zip(letters,num):
if line in num_letter_dict:
num_letter_dict[line].append(value) # append the element
else:
num_letter_dict[line] = [value]
Try the following code, I have modified the for loop and used extend
for i, letter in zip(num, letters):
if i not in num_letter_dict:
num_letter_dict[i] = []
num_letter_dict[i].extend(letter) #change over here
print(num_letter_dict)
Ahh, I had to deal with this same issue yesterday. While the other submitted answers would work, might I recommend the defaultdict from the Collections module?
from collections import defaultdict
num = ['0', '2', '3', '0','7']
letters = ['a', 'b', 'c', 'd','e']
num_letter_dict = defaultdict(list)
for n, letter in zip(num, letters):
num_letter_dict[n].append(letter)
print(num_letter_dict)
I like this approach because it allows the defaultdict class to do the construction of the list internally, rather than muddying up one's own source code with if-statements.
You can test-execute this solution on IDEOne: https://ideone.com/9Dg9Rk
I have a list my_list = ['a', 'b', 'c', 'd'] and I need to create a dictionary which looks like
{ 'a': ['a', 'b', 'c', 'd'],
'b': ['b', 'a', 'c', 'd'],
'c': ['c', 'a', 'b', 'd'],
'd': ['d', 'a', 'b', 'c'] }
each element as its value being the list but the first element is itself.
Here is my code
my_list = ['1', '2', '3', '4']
my_dict=dict()
for x in my_list:
n = my_lst[:]
n.remove(x)
n= [x] + n[:]
my_dict[x] = n
print my_dict
which gives
{'1': ['1', '2', '3', '4'],
'3': ['3', '1', '2', '4'],
'2': ['2', '1', '3', '4'],
'4': ['4', '1', '2', '3']}
as required.
But I don't think that's the most optimal way of doing it. Any help to optimize will be appreciated.
>>> seq
['a', 'b', 'c', 'd']
>>> {e: [e]+[i for i in seq if i != e] for e in seq}
{'a': ['a', 'b', 'c', 'd'],
'b': ['b', 'a', 'c', 'd'],
'c': ['c', 'a', 'b', 'd'],
'd': ['d', 'a', 'b', 'c']}
A faster approach (than the accepted answer) for larger lists is
{e: [e] + seq[:i] + seq[i+1:] for i, e in enumerate(seq)}
Relative timings:
In [1]: seq = list(range(1000))
In [2]: %timeit {e: [e]+[i for i in seq if i != e] for e in seq}
10 loops, best of 3: 40.8 ms per loop
In [3]: %timeit {e: [e] + seq[:i] + seq[i+1:] for i, e in enumerate(seq)}
100 loops, best of 3: 6.03 ms per loop
You can get hacky with a dictionary comprehension:
my_dict = {elem: list(sorted(my_list, key=lambda x: x != elem)) for elem in my_lst}
This works on the fact that the sorted function performs a stable sort, and False is less than True
Edit: This method is less clear and probably slower, use with caution.
The challenge is that I want to count the number of times a certain pattern of items occurs in a sub-list at certain indices.
For example, I'd like to count the number of times a unique patter occurs at index 0 and index 1. 'a' and 'z' occur three times below at index 0 and index 1 while '1' and '2' occur two times below at index 0 and index 1. I'm only concerned at the pair that occurs at index 0 and 1 and I'd like to know the count of unique pairs that are there and then append that count back to the sub-list.
List = [['a','z','g','g','g'],['a','z','d','d','d'],['a','z','z','z','d'],['1','2','f','f','f'],['1','2','3','f','f'],['1','1','g','g','g']]
Desired_List = [['a','z','g','g','g',3],['a','z','d','d','d',3],['a','z','z','z','d',3],['1','2','f','f','f',2],['1','2','3','f','f',2],['1','1','g','g','g',1]]
Currently, my attempt is this:
from collections import Counter
l1 = Counter(map(lambda x: (x[0] + "|" + x[1]),List)
Deduped_Original_List = map(lambda x: Counter.keys().split("|"),l1)
Counts = map(lambda x: Counter.values(),l1)
for ele_a, ele_b in zip(Deduped_Original_List, Counts):
ele_a.append(ele_b)
This clearly doesn't work because in the process I lose index 2,3, and 4.
You can use list comprehension with collections.Counter:
from collections import Counter
lst = [['a','z','g','g','g'],['a','z','d','d','d'],['a','z','z','z','d'],['1','2','f','f','f'],['1','2','3','f','f'],['1','1','g','g','g']]
cnt = Counter([tuple(l[:2]) for l in lst])
lst_output = [l + [cnt[tuple(l[:2])]] for l in lst]
print lst_output
Ouput:
[['a', 'z', 'g', 'g', 'g', 3], ['a', 'z', 'd', 'd', 'd', 3], ['a', 'z', 'z', 'z', 'd', 3], ['1', '2', 'f', 'f', 'f', 2], ['1', '2', '3', 'f', 'f', 2], ['1', '1', 'g', 'g', 'g', 1]]
>>> import collections
>>> List = [['a','z','g','g','g'],['a','z','d','d','d'],['a','z','z','z','d'],['1','2','f','f','f'],['1','2','3','f','f'],['1','1','g','g','g']]
>>> patterns = ['az', '12']
>>> answer = collections.defaultdict(int)
>>> for subl in List:
... for pattern in patterns:
... if all(a==b for a,b in zip(subl, pattern)):
... answer[pattern] += 1
... break
...
>>> for i,subl in enumerate(List):
... if ''.join(subl[:2]) in answer:
... List[i].append(answer[''.join(subl[:2])])
...
>>> List
[['a', 'z', 'g', 'g', 'g', 3], ['a', 'z', 'd', 'd', 'd', 3], ['a', 'z', 'z', 'z', 'd', 3], ['1', '2', 'f', 'f', 'f', 2], ['1', '2', '3', 'f', 'f', 2], ['1', '1', 'g', 'g', 'g']]
>>>
I like the Counter approach of YS-L. Here is another approach:
>>> List = [['a','z','g','g','g'], ['a','z','d','d','d'], ['a','z','z','z','d'],['1','2','f','f','f'], ['1','2','3','f','f'], ['1','1','g','g','g']]
>>> d = {}
>>> for i in List:
key = i[0] + i[1]
if not d.get(key, None): d[key] = 1
else: d[key] += 1
>>> Desired_List = [li + [d[li[0] + li[1]]] for li in List]
>>> Desired_List
[['a', 'z', 'g', 'g', 'g', 3], ['a', 'z', 'd', 'd', 'd', 3], ['a', 'z', 'z', 'z', 'd', 3], ['1', '2', 'f', 'f', 'f', 2], ['1', '2', '3', 'f', 'f', 2], ['1', '1', 'g', 'g', 'g', 1]]