Is there a way to check if a value is unique for a specific list, within a dictionary of lists? If yes, I would like to know in which key/list pair/s the value is present.
For example:
{1: [3, 4, 5], 2: [4], 3: [5], 6: [3, 5, 9], 8: [3 ,8]}
I want to check if 3 is present in any of the other lists within the dictionary, besides 1: [3, 4, 5(compare it with all others). Since it is, then I must receive as a result 6 and 8, because these are the keys, which corresponding lists have this value.
Try this:
def find_n(nums, target, exception):
res = []
for n, nums_list in nums.items():
exception_key = [i for i in exception][0]
if n != exception_key and nums_list != exception[exception_key]:
if target in nums_list:
res.append(n)
return res
if __name__ == '__main__':
nums = {1: [3, 4, 5], 2: [4], 3: [5], 6: [3, 5, 9], 8: [3, 8]}
target = 3
exception = {1: [3, 4, 5]}
print(find_n(nums, target, exception))
Reuslt:
[6, 8]
You can enter the value you are looking for and then loop over all the dictionaries to see if its in them.
Take this as pseudo code:
int val = 3
for(keys in mydict):
if(mydict.key.contains(val())
print(mydict.key)
You could also save the dictionaries in a list, so that you have a list of dicts with your corresponding value.
Not entirely sure if this is what you meant but:
def unique(list1):
# initialize a null list:
unique_list = []
# traverse for all elements:
for x in list1:
# check if exists in unique_list or not
if x not in unique_list:
unique_list.append(x)
# printing the list:
for x in unique_list:
print(x, end=' ')
list1 = [10, 20, 10, 30, 40, 40]
print("the unique values from 1st list is")
unique(list1)
list2 = [1, 2, 1, 1, 3, 4, 3, 3, 5]
print("\nthe unique values from 2nd list is")
unique(list2)
This code will loops through all the values and ensure that they are not repeated.
You could write some simple helper functions like so:
my_dict = {1: [3, 4, 5], 2: [4], 3: [5], 6: [3, 5, 9], 8: [3 ,8]}
def keys_containing_element(dict_of_lists: dict, element: int) -> list:
"""Return all keys in dict_of_list whose list contains element"""
return [key for key in dict_of_lists.keys() if element in dict_of_lists[key]]
def is_element_unique(dict_of_lists: dict, element: int) -> list:
"""Return true if element is in exactly one of the lists in dict_of_lists"""
return True if len(keys_containing_element(dict_of_lists, element)) == 1 else False
Now,
print(keys_containing_element(my_dict, 3))
print(is_element_unique(my_dict, 3))
print(keys_containing_element(my_dict, 9))
print(is_element_unique(my_dict, 9))
outputs
[1, 6, 8]
False
[6]
True
Related
I am trying to write a function that get a list of lists with different length as input and return the zipped result.
What I am looking for is that to expand my code below to any amount of lists. (I cannot use Zip Longest function since I am trying to do this on our system that does not have most of python functions including
zip longest function)
Here is my code:
a = [[1,2,3,4],[5,6],[7,8,9]]
def myzip(a):
temp1=[]
temp2=[]
temp3=[]
lens=[]
t=1
for i in a:
if(t==1):
temp1=i
lens.append(len(temp1))
t+=1
elif(t==2):
temp2=i
lens.append(len(temp2))
t+=1
elif(t==3):
temp3=i
lens.append(len(temp3))
for i in range(max(lens)):
if(i<len(temp1)):
print(temp1[i])
if(i<len(temp2)):
print(temp2[i])
if(i<len(temp3)):
print(temp3[i])
myzip(a)
Output:
1
5
7
2
6
8
3
9
4
This function works only for 3 lists because I am using Temp lists in order to achieve the zipped result But I want to make this code works for any number of lists. for example I able to run for [[1,2,3,4],[5,6],[7,8,9],[11,33]] or [[1,2,3,4],[5,6]] or [[1,2,3,4],[5,6],[7,8,9],...,[25,22]]
How about this:
from itertools import zip_longest
lists = [[1, 2, 3, 4], [5, 6], [7, 8, 9], [11, 33]]
for item in [x for t in zip_longest(*lists) for x in t]:
if item is not None:
print(item)
Output:
1
5
7
11
2
6
8
33
3
9
4
Or to just get them as a list:
items = [x for t in zip_longest(*lists) for x in t if x is not None]
Note: #MarkM made a worthwhile remark - if your source data contains None, this approach will have a problem in that it will filter them out. You should tell zip_longest to use a different fillvalue in that case, that does not show up in your data. For example:
items = [x for t in zip_longest(*lists, fillvalue='') for x in t if x is not None]
If you cannot import itertools for very specific reasons (as mentioned in the comments), you could just use the implementation shown in the documentation (https://docs.python.org/3/library/itertools.html#itertools.zip_longest):
def repeat(object, times=None):
if times is None:
while True:
yield object
else:
for i in range(times):
yield object
def zip_longest(*args, fillvalue=None):
iterators = [iter(it) for it in args]
num_active = len(iterators)
if not num_active:
return
while True:
values = []
for i, it in enumerate(iterators):
try:
value = next(it)
except StopIteration:
num_active -= 1
if not num_active:
return
iterators[i] = repeat(fillvalue)
value = fillvalue
values.append(value)
yield tuple(values)
Something like this could also work for you:
def flatten_list(my_list):
flat_list = []
for element in my_list:
if type(element) is list: #if element is a list, iterate through it
for item in element:
flat_list.append(item)
else:
flat_list.append(element)
return flat_list
nested_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10],[1,2,3],[1,2,4],[4,6,7,8]]
print('Original List', nested_list)
print('Flat List', flatten_list(nested_list))
Output
Original List [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10], [1, 2, 3], [1, 2, 4], [4, 6, 7, 8]]
Flat List [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 1, 2, 4, 4, 6, 7, 8]
I'm working on a problem, and it would be much easier to solve if I had an elegant way to convert a multi dimensional list of n elements into a dictionary of keys corresponding with the index and values corresponding with the list values.
Example:
[[1,2,3],[4,5,6],[7,8,9]] => {0:[1,2,3], 1:[4,5,6], 2:[7,8,9]}
Is there a simple way to do this with Python?
To expand on my comment:
>>> array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> {index: list(value) for index, value in enumerate(array)}
{0: [1, 2, 3], 1: [4, 5, 6], 2: [7, 8, 9]}
changed value to list(value) to avoid byref v. byval issues
You can try using enumerate on the list:
new_dict = {}
for itr, ele in enumerate(array):
new_dict[itr] = ele
return new_dict
There may be another solution that is a little less code but this should work for what you are trying to do, assuming the index should be the key.
EDIT:
{itr: ele for itr, ele in enumerate(array)}
Some steps follow you can convert your any kind of multi dimensional list into dictionary
Step 1 :
call your list :
mylist = [[1,2,3],[4,5,6],[7,8,9]]
Step 2:
stored dict variable name
mydict = {}
for i in range(len(mylist)):
mydict[i] = mylist[i]
print(mydict)
Result :
{0: [1, 2, 3], 1: [4, 5, 6], 2: [7, 8, 9]}
[Note : The result is tested ]
I am working on a dictionary containing keys and values, with the keys being IDs and each value being a list. How could I check a condition like, "if there is 6 as the FIRST element of any list"?
dict_ = {0: [1, 2, 4, 1], 1: [3, 8, 4, 7], 2: [6, 2, 4, 2], 3: [5, 1, 3, 6]}
if 6 in dict_.values[0]():
print("6 is in the first cell of one of the lists")
return(True)
This looks like what I want to do but it's not the right syntax and gives me "TypeError object is not sub scriptable". I expect it to return True only if there is a 6 on the [0] of one of the lists.
You can use the built-in function any for a one-liner:
any(val[0] == 6 for val in dict.values())
Add an if val at the end for extra safety, in case any of the lists are null or empty.
Answer:
dictionary = {0: [1, 2, 4, 1], 1: [3, 8, 4, 7], 2: [6, 2, 4, 2], 3: [5, 1, 3, 6]}
for key, val in dictionary.items():
if val[0] == 6:
print("6 is present at 1 st position :", key,":",val)
Output:
6 is present at 1 st position : 2 : [6, 2, 4, 2]
First, never shadow a built-in: use d or dict_ instead of dict as a variable name. Second, note that dict.values() returns a view, you can't apply __getitem__ (or []) on a view object, let alone a method which you haven't called via parentheses.
You can modify your function and use simple iteration:
d = {0: [1, 2, 4, 1], 1: [3, 8, 4, 7], 2: [6, 2, 4, 2], 3: [5, 1, 3, 6]}
def check_value(d, val, pos=0):
for value in d.values():
if value[pos] == val:
return True
return False
res = check_value(d, 6) # True
You can also use any with a generator expression:
def check_value_any(d, val, pos=0):
return any(value[pos] == val for value in d.values())
This is lazy, i.e. if the conditional is met at any point any returns True and the function returns True. However, this may be less efficient as generators carry additional overhead.
I'm not sure what you mean but I'll try to answer you.
First of all, you iterate through dictionary like this:
for key, values in d.items():
you can also use d.keys() or d.values(), depending on what you need.
Now, if you need to see if 6 is on the first position in any list in dictionary, you can do it like this:
for key, value in d.items():
if value[0] == 6:
return True
If you want to see if number 6 appears in the first list (of the first key), you can do that with:
for value in list(d.keys())[0]:
if value == 6:
return True
Let's get the values of the dict first:
dict_ = {0: [1, 2, 4, 1], 1: [3, 8, 4, 7], 2: [6, 2, 4, 2], 3: [5, 1, 3, 6]}
for key, val in dict_.items():
print(val)
OUTPUT:
[1, 2, 4, 1]
[3, 8, 4, 7]
[6, 2, 4, 2]
[5, 1, 3, 6]
Now to check if the values (list) has a 6 on the first index:
for key, val in dict_.items(): # for each key, val (list) in the dict
if val[0] == 6: # [0] for the first index of each list
print("6 found at the first index in the list: ", val)
OUTPUT:
6 found at the first index in the list: [6, 2, 4, 2]
I have a list of lists which is
my_list=[[9, 10, 1], [1, 7, 5, 6, 11], [0, 4], [4, 2, 9]]
I want to sort this list such that it looks like this:
result=[[0, 4], [4, 2, 9],[9, 10, 1], [1, 7, 5, 6, 11]]
The conditions are:
1. The list should start with the element containing zero.
2. The last element of a list should be same as first element of the next list and so on.
3. The elements inside the sub-lists should be in the same order as the original list.
Thank you.
The fast solution is to build a dict that maps numbers to sublists based on the first element:
dct = {sublist[0]: sublist for sublist in my_list}
# {0: [0, 4], 9: [9, 10, 1], 1: [1, 7, 5, 6, 11], 4: [4, 2, 9]}
And then, starting with the number 0, looking up the next sublist that needs to be added in the dict:
result = []
num = 0 # start with the sublist where the first element is 0
while True:
try:
# find the sublist that has `num` as the first element
sublist = dct[num]
except KeyError:
# if there is no such sublist, we're done
break
# add the sublist to the result and update `num`
result.append(sublist)
num = sublist[-1]
This runs in linear O(n) time and gives the expected results:
[[0, 4], [4, 2, 9], [9, 10, 1], [1, 7, 5, 6, 11]]
You could check for each permutation of your list, if they are a valid permutation. It might be possible to write a more efficient algorithm, but this one does not assume that there is exactly one possible solution.
from itertools import permutations
my_list=[[9, 10, 1], [1, 7, 5, 6, 11], [0, 4], [4, 2, 9]]
def sortCheck(a):
if a[0][0] != 0:
return False
for i in range(0, len(a) - 1):
if a[i][-1] != a[i+1][0]:
return False
return True
result_list = []
for permutation in permutations(my_list):
if sortCheck(permutation):
result_list.append(list(permutation))
Not a very nice implementation, but it works:
my_list=[[9, 10, 1], [1, 7, 5, 6, 11], [0, 4], [4, 2, 9]]
new_list = []
index = 0
while my_list:
index = [item[0] for item in my_list].index(index)
item = my_list[index]
del my_list[index]
new_list.append(item)
index = item[-1]
print(new_list)
A ValueError is raised when no sublist is found that meet the criterion
def sortList(list)
hash = {}
list.each do |value|
hash[value[0]] = value
end
key = 0
sorted = []
list.each do |k|
item = hash[key.to_i]
key = item[-1]
sorted << item
end
sorted
end
From this list:
N = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
I'm trying to create:
L = [[1],[2,2],[3,3,3],[4,4,4,4],[5,5,5,5,5]]
Any value which is found to be the same is grouped into it's own sublist.
Here is my attempt so far, I'm thinking I should use a while loop?
global n
n = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5] #Sorted list
l = [] #Empty list to append values to
def compare(val):
""" This function receives index values
from the n list (n[0] etc) """
global valin
valin = val
global count
count = 0
for i in xrange(len(n)):
if valin == n[count]: # If the input value i.e. n[x] == n[iteration]
temp = valin, n[count]
l.append(temp) #append the values to a new list
count +=1
else:
count +=1
for x in xrange (len(n)):
compare(n[x]) #pass the n[x] to compare function
Use itertools.groupby:
from itertools import groupby
N = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
print([list(j) for i, j in groupby(N)])
Output:
[[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]
Side note: Prevent from using global variable when you don't need to.
Someone mentions for N=[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 1] it will get [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5], [1]]
In other words, when numbers of the list isn't in order or it is a mess list, it's not available.
So I have better answer to solve this problem.
from collections import Counter
N = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
C = Counter(N)
print [ [k,]*v for k,v in C.items()]
You can use itertools.groupby along with a list comprehension
>>> l = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
>>> [list(v) for k,v in itertools.groupby(l)]
[[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]
This can be assigned to the variable L as in
L = [list(v) for k,v in itertools.groupby(l)]
You're overcomplicating this.
What you want to do is: for each value, if it's the same as the last value, just append it to the list of last values; otherwise, create a new list. You can translate that English directly to Python:
new_list = []
for value in old_list:
if new_list and new_list[-1][0] == value:
new_list[-1].append(value)
else:
new_list.append([value])
There are even simpler ways to do this if you're willing to get a bit more abstract, e.g., by using the grouping functions in itertools. But this should be easy to understand.
If you really need to do this with a while loop, you can translate any for loop into a while loop like this:
for value in iterable:
do_stuff(value)
iterator = iter(iterable)
while True:
try:
value = next(iterator)
except StopIteration:
break
do_stuff(value)
Or, if you know the iterable is a sequence, you can use a slightly simpler while loop:
index = 0
while index < len(sequence):
value = sequence[index]
do_stuff(value)
index += 1
But both of these make your code less readable, less Pythonic, more complicated, less efficient, easier to get wrong, etc.
You can do that using numpy too:
import numpy as np
N = np.array([1,2,2,3,3,3,4,4,4,4,5,5,5,5,5])
counter = np.arange(1, np.alen(N))
L = np.split(N, counter[N[1:]!=N[:-1]])
The advantage of this method is when you have another list which is related to N and you want to split it in the same way.
Another slightly different solution that doesn't rely on itertools:
#!/usr/bin/env python
def group(items):
"""
groups a sorted list of integers into sublists based on the integer key
"""
if len(items) == 0:
return []
grouped_items = []
prev_item, rest_items = items[0], items[1:]
subgroup = [prev_item]
for item in rest_items:
if item != prev_item:
grouped_items.append(subgroup)
subgroup = []
subgroup.append(item)
prev_item = item
grouped_items.append(subgroup)
return grouped_items
print group([1,2,2,3,3,3,4,4,4,4,5,5,5,5,5])
# [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]