find sum and minimum of nested list - python

How do we calculate with having both int element and list of list element.
def minelementNested(list):
minele = list[0]
sumele = 0
count = 0
for i in list1:
if type(i) is int:
sumele = sumele+i
if i < minele:
minele = i
count = count +1
else:
sumele += sum(i)
count = count + len(i)
else_min = min(i)
if else_min < minele:
minele = else_min
avg = sumele/count
print(avg)
return minele
list1 = [23,24,[10,11,12],56,85,[34,45,6]]
minelementNested(list1)
Is there any other way to do this?
or can we convert the individual int element to list and go ahead with list comprehension.
please suggest.
Thank you.

If you only have one level of nested list to worry about, you can do this as a one-liner that normalizes the nested list to a 2D list of lists of ints, and then unpacks it in a nested generator:
>>> nums = [23,24,[10,11,12],56,85,[34,45,6]]
>>> min(n for i in nums for n in (i if isinstance(i, list) else [i]))
6
If you have arbitrary levels of nesting, use a recursive function:
>>> def nested_min(arr):
... if isinstance(arr, int):
... return arr
... return min(nested_min(i) for i in arr)
...
>>> nested_min(nums)
6
>>> nested_min([10, 11, 12, [[1, 2], 3, 4], 5])
1

Related

Remove duplicates from a list in-place

How can one make a list contain only unique items while preserving order AND updating it in-place?
I know that a set can be used, but it will not guarantee ordering.
Use a supporting set, and a while loop:
def unique(arr):
tmp_set = set()
i = 0
while i < len(arr):
if arr[i] in tmp_set:
del arr[i]
else:
tmp_set.add(arr[i])
i += 1
The above will update the array in-place, and preserve ordering of the elements as well.
another way without sets:
def deduplicate_in_place(items):
_tmp_list = []
for item in items:
if item not in _tmp_list:
_tmp_list.append(item)
items[:] = _tmp_list
Enhanced CodeSpeed solution.
lst = [1, 2, 2, 1, 1]
seen = set()
length = len(lst) - 1
i = 0
while i < length:
if lst[i] in seen:
del lst[i]
i -= 1
seen.add(lst[i])
i += 1
length = len(lst)
print(lst)
You can use a loop to iter over the entries in the list one by one and insert them into a newlist only if they are not present in the new list.
lst = [3,3,3,1,2,2,4]
my_list = []
for i in lst:
if i not in my_list:
my_list.append(i)
my_list
# Output - [3, 1, 2, 4]
I hope this helps.

How to multiply two sublists within the same list?

I am new to python and SO. I want to multiply each element of lists in a list of lists to another list lying in the same list of lists and compare it with a reference value. This will be more clear with an example:
for L = [[1,2,3,4,5,10],[3,2,4,1,5,10]] ##there can be more than 2 lists in this list of lists
I want only those pairs whose product results in 10.
Out: L = [[1,10],[2,5]]
Edit: I prefer a method without any imports, since I am doing this for building logic and my editor doesn't contain any modules to import. Also, if there are more than 2 lists in a list of lists For eg. there are 3 Lists in a list of lists: then I want triplets for that sake. ANd if 4 lists then I need quadruples.
Here's my code attempt as requested.
N = []
J = []
F = []
Z = []
S = []
O = []
num = input("Enter no. of elements in list")
print ('Enter numbers')
prod = 1
for i in range(int(num)):
n = input("num :")
N.append(int(n))
for x in N:
prod = prod*x
print (prod)
k = int(input("Enter no. of splits:"))
##d = [[] for x in xrange(k)]
##var_dict = []
for o in range(1,prod+1):
if prod%o == 0:
J.append(o)
print (J)
for g in range(k):
O.append(J*(k-1))
print (O)
for a in range(len(O)):
for b in range(len(O)):
if O[i]*O[i+1] == prod:
Z.extend(O)
##Z = [[a, b] for a in J for b in F if a*b == prod] ##imp
print (Z)
for e in Z:
if e not in S and sorted(e) not in S:
S.append(e)
print (S)
You can use itertools.product to find groups of numbers and filter them based on their product
>>> from itertools import product
>>> from functools import reduce
>>> lst = [[1,2,3,4,5,10],[3,2,4,1,5,10]]
>>> ans = [p for p in product(*lst) if reduce(lambda x,y:x*y, p) == 10]
>>> # Remove duplicates
>>> ans = list(map(list, set(map(frozenset, ans))))
>>> print (ans)
[[1, 10], [2, 5]]
>>>
In a comment you say you say you want code without any imports. Importing product from itertools and reduce do simplify and speed the code, but the job can be done without imports. Here is a recursive solution. I am not quite satisfied with this code but it seems to work and passes all my tests. I generalized the problem somewhat so that the input can have tuples or other sequences and not just lists.
def prod_is_target(seq_of_seqs, target):
"""Return a list of lists, where each sublist contains one member
of each input subsequence in order, and the product of those
members equals the target value. If there is no such list possible,
return None. If seq_of_seqs is empty, return an empty list if the
target is 1 and return None otherwise.
"""
if not seq_of_seqs: # if is empty sequence
return [] if target == 1 else None
result = []
for val in seq_of_seqs[0]:
if target % val: # skip if target is not a multiple of val
continue
prodlists = prod_is_target(seq_of_seqs[1:], target // val)
if prodlists is None: # skip if failed with later sublists
continue
if not prodlists: # if is empty list
result.append([val])
else:
for prodlist in prodlists:
result.append([val] + prodlist)
return result if result else None
print(prod_is_target([[1,2,3,4,5,10], [3,2,4,1,5,10]], 10))
The printout from that code is
[[1, 10], [2, 5], [5, 2], [10, 1]]
I'll leave it to you to remove what you consider to be duplicates. I can think of situations where you would want this full list, however.

Dictionary autoarranging? [duplicate]

This question already has answers here:
How do I sort a dictionary by value?
(34 answers)
Closed 5 years ago.
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None:
return None
start = head
prev = head.val
a = {prev:1}
#o = [prev]
head = head.next
while head != None:
if head.val == prev:
a[prev] += 1
else:
prev = head.val
a[prev] = 1
#o.append(prev)
head = head.next
b = ListNode(0)
ans = b
for i in a: # can use for i in o
if a[i] == 1:
c = ListNode(i)
b.next = c
b = b.next
return ans.next
I am trying to remove duplicate items from a sorted linked list, eg.[1,2,3,3,4,4,5,6,6,6] -> [1,2,5]. Can someone walk through the code and tell me what will be the final value of a is for the linked list 2->1->None. It should be {2:1, 1:1} but answer comes out to be {1:1, 2:1}...why?
dict object doesn't remember the order of elements which are added to the dictionary. If you want to preserve the ordering of the elements you can use OrderedDict.
O(N) option using groupby
>>> from itertools import groupby
>>> [k for k,g in groupby([1,2,3,3,4,4,5,6,6,6]) if len(list(g)) == 1]
[1, 2, 5]
Try the following:
>>> l = [1,2,3,3,4,4,5,6,6,6]
>>> [i for i in l if l.count(i) == 1]
This preserves the order of items in l.
Here's an approach in O(n) time (in Python 3), regardless of whether the list is sorted.
>>> lst = [1, 2, 3, 3, 4, 4, 5, 6, 6, 6]
>>> unique = {}
>>> for item in lst:
... if item in unique:
... unique[item] += 1
... else:
... unique[item] = 1
...
>>> [k for k, v in unique.items() if v == 1]
[1, 2, 5]
The statement for item in lst: ... is O(n).
The expression item in unique is O(1).
The statement unique[item] = 1 is O(1), and so is unique[item] += 1.
The expression [k for k, v in unique.items() if v == 1] is O(n).
So, calculating the time complexity of the for statement:
O(n) * (O(1) + max(O(1), O(1)))
O(n) * (O(1) + O(1))
O(n) * O(1)
O(n)
Add that to the time complexity of the list comprehension, and you have O(n) + O(n), which is O(2n). Drop the constant, and you have O(n).
This answer assumes that all you want to do is to create another list, only keeping the values that occur once.
One way of doing it would be to use groupby from itertools and then filter based on the length of each group.
# Assuming 's' holds our list
[i for i,k in itertools.groupby(s) if len(list(k)) == 1]
EDIT Reading your question again, it seems this solution might not work, unless the linked list type you're using conforms to the iterator protocol. At any rate, it certainly won't produce a list as output, although you could replace the list comprehension with a generator expression and build a linked list from that.

Python multiple loops

A = [[[1,2,3],[4]],[[1,4],[2,3]]]
Here I want to find lists in A which sum of all sublists in list not grater than 5.
Which the result should be [[1,4],[2,3]]
I tried a long time to solve this problem in python. But I still can't figure out the right solution, which I stuck at loop out multiple loops. My code as follows, but its obviously wrong, how to correct it?
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
z = []
for l in A:
for list in l:
sum = 0
while sum < 5:
for i in list:
sum+=i
else:
break
else:
z.append(l)
print z
Asking for help~
Simplification of #KindStranger method in a one-liner:
>> [sub for x in A for sub in x if max(sum(sub) for sub in x) <= 5]
[[1, 4], [2, 3]]
A simple solution which you can think of would be like this -
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
r = [] # this will be our result
for list in A: # Iterate through each item in A
f = True # This is a flag we set for a favorable sublist
for item in list: # Here we iterate through each list in the sublist
if sum(item) > 5: # If the sum is greater than 5 in any of them, set flag to false
f = False
if f: # If the flag is set, it means this is a favorable sublist
r.append(list)
print r
But I'm assuming the nesting level would be the same. http://ideone.com/hhr9uq
This should work for your problem:
>>> for alist in A:
... if max(sum(sublist) for sublist in alist) <= 5:
... print(alist)
...
[[1, 4], [2, 3]]
The one with all()
[t for item in A for t in item if all(sum(t)<=5 for t in item)]

Returning a copy of the list in which one instance of every value is removed

What i have only removes duplicated items and sorts them. I need to remove one instance of every item and return a new list with the items in it. This is what i have:
def rem(nlst):
n = []
for x in nlst:
if x not in n:
n.append(x)
n.sort()
return n
This is what it should do:
>>> rem([4])
[]
>>> rem([4,4])
[4]
>>> rem([4, 1, 3, 2])
[]
>>> rem([2, 4, 2, 4, 4])
[2, 4, 4]
An easy implementation is to use collections.Counter:
def rem(iterable):
c = collections.Counter(iterable)
for k in c:
c[k] -= 1
return sorted(c.elements())
In Python versions before 2.7, collections.Counter is not available. You can use a set to record the items you already saw instead:
def rem(iterable):
result = []
seen = set()
for x in iterable:
if x in seen:
result.append(x)
else:
seen.add(x)
result.sort()
return result
A slight tweak to your code seems to work ok. Just added a variable to track the current value and only append a new one if you have already seen that value:
def rem(nlist):
n = []
nlist.sort()
cur = None
for x in nlist:
if x == cur:
n.append( x )
cur = x
return n
~

Categories