Python test if list items are far apart [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have a list in python that might look something like this:
list_example = [1,2,20,21,22]
As you can see, all the numbers are close to their adjacent list items, except for the jump between 2 and 20.
How would I get Python to notice this larger jump and store the list item's index?

You can use zip() to iterate through every i and i+1 element, and then compute the difference between the two adjacent elements.
for a, b in zip(list_example, list_example[1:]):
diff = b - a
if diff > 10:
print("Jump between %d and %d" % (a, b))
But then, it is up to you to define what is exactly a "jump".
If you need the index, you can make use of enumerate():
for i, (a, b) in enumerate(zip(list_example, list_example[1:])):
...

You could get the average distance between elements and then output those indices where the distance to the last element is larger than that average.
>>> lst = [1,2,20,21,22]
>>> avg_dst = sum(abs(a-b) for a, b in zip(lst, lst[1:])) / (len(lst)-1)
>>> [i for i in range(1, len(lst)) if abs(lst[i] - lst[i-1]) > avg_dst]
[2]

You need a set number that is the number that will set a jump off.
This means looping over comparing the current number with its neighbour and alerting whenever the numbers have a difference of your set jump number.
This is assuming your list is already sorted.

Assuming that the values are arranged in ascending order (like your example), you could created a sorted list of (DIFF, INDEX) pairs.
xs = [1, 2, 20, 21, 22]
pairs = sorted((xs[i] - xs[i-1], i) for i in range(1, len(xs)))
print(pairs) # [(1, 1), (1, 3), (1, 4), (18, 2)]

Related

Subtracting a tuples of the list [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 months ago.
Improve this question
I have a list of tuples
lst = [(1,2,3),(1,2,3),(7,8,9)]
And
I want to find the difference between previous tuple from the next like this:
ans = [(0,0,0), (6,6,6)]
How can I do this in Python?
You can iterate over the data and use the sub method from the operator package to subtract the tuples:
from operator import sub
data = [(1,2,3),(1,2,3),(7,8,9)]
diff = [tuple(map(sub, data[i+1], data[i])) for i in range(0, len(data)-1)]
You could also use a for loop instead of the list comprehension if you prefer. The tuple subtraction is from here: Elegant way to perform tuple arithmetic
from functools import reduce, partial
from operator import sub
my_list = [(1,2,3),(1,2,3),(7,8,9)]
diff_list = list(map(partial(reduce, lambda a, b: tuple(map(sub, a, b))), zip(my_list[1:], my_list)))
To break it down:
zip(my_list[1:], my_list)
This creates a new iterator which yields iterables consisting of every next element of the list followed by the previous.
partial(reduce, lambda a, b: tuple(map(sub, a, b)))
This creates a function which when given an iterable whose elements consist of tuples, will return a new tuple containing the difference between the first and the second tuples. It could be more tuples, but in our case, we only ever pass to this function an iterable consisting of two tuples, it will always do what we want.
Try:
lst = [(1, 2, 3), (1, 2, 3), (7, 8, 9)]
out = [tuple(b - a for a, b in zip(t1, t2)) for t1, t2 in zip(lst, lst[1:])]
print(out)
Prints:
[(0, 0, 0), (6, 6, 6)]

Merging two lists without duplicates, and calculate the mean of duplicate indices in separate lists [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I know that the title isn't very clear, so I'll give an example that will make it far easier to understand:
Let's say I have two pairs of lists; [a_time, a_pos], [b_time, b_pos], that I wish to combine based on the values in the 'time' lists (a_time & b_time). However, I also want to calculate the average values in the 'position' lists (a_pos & b_pos) based on the merge between the time lists.
To give some example numbers:
a_time = [0, 2] # order of indices matters, therefore a_time[0] = 0, corresponds to a_pos[0] = 10, etc.
b_time = [1, 2]
a_pos = [10, 9]
b_pos = [9, 11]
Here, I could merge the two time lists (removing the duplicates) a number of ways to make 'new_time', such as:
new_time = np.unique(a_time + b_time) # set() could be also used instead of np.unique()
print(new_time) # [0, 1, 2] (note it does not matter if a list or an array is returned)
I would then like to merge the two position lists, to make 'new_pos'. However, both 'a' and 'b' have two matching times (2), so I would like to average the positions at those times, before creating the new list. Hence this stage would look something like:
# new_pos = (Some method of merging & averaging based on new_time)
print(new_pos) # [10, 9, 10] (where the second 10 comes from (9 + 11) / 2, as two times were merged)
Does anybody know how to efficiently perform this merging operation?
(This solution would then extend to another parameter pair; 'a_bound' & 'b_bound', where a similar operation to the 'pos' lists would be performed, but I have chosen not to include it in this question to avoid confusion).
Thank you in advance!
Start by ziping the times and positions so you can combine them into one list without losing the associations between the original lists, e.g.:
>>> list(zip(a_time, a_pos)) + list(zip(b_time, b_pos))
[(0, 10), (2, 9), (1, 9), (2, 11)]
Now you need to group the identical times together. You could do this all in a single statement with itertools.groupby but I think a slightly more verbose operation with defaultdict is a little easier to follow:
>>> from collections import defaultdict
>>> positions = defaultdict(list)
>>> for t, p in list(zip(a_time, a_pos)) + list(zip(b_time, b_pos)):
... positions[t].append(p)
...
>>> list(positions.items())
[(0, [10]), (2, [9, 11]), (1, [9])]
Now we just need the averages:
>>> from statistics import mean
>>> sorted([(t, mean(p)) for t, p in positions.items()])
[(0, 10), (1, 9), (2, 10)]
Or if you just want the positions without the times:
>>> [mean(p) for t, p in sorted(positions.items())]
[10, 9, 10]

Generating all combinations using Python [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Say I've a list with a fixed size and elements.
I wish to create set of all possible combinations of the elements inside the array. How do I achieve this?
In python I've tried to use itertools like this:
import itertools
a = [4, 7]
for L in range(0, len(a)+1):
for subset in itertools.combinations(a, L):
print(subset)
Howsoever, this gives me an output(),(4),(7),(4,7) as in tuples. I want 4,7,47,74 as my desired output in a list or array(C++) and not to print them after each loop iteration.
I don't know if that's permutation or combination. So kindly bear with me and help.
From your sample output (which by the way is not in agreement with your input), it is clear that you don't need combinations but permutations from itertools. You can use join to merge your two numbers for printing purpose.
Most importantly, you should start your loop over L from 1 because you need at least length of 1 to generate the permutations other wise you will get empty lists (tuples) as you mentioned in your question.
import itertools
a = [4, 7]
lst = []
for L in range(1, len(a)+1):
for subset in itertools.permutations(a, L):
lst.append(''.join(str(x) for x in subset))
for l in lst:
print (l)
Output
4
7
47
74

Accessing occurrence groups for high frequency elements in list [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have several lists where some of the elements occur in more than one. An example would be
lst[0]
Output: [1,2,3]
lst[1]
Output: [1,2]
lst[2]
Output: [3]
So far, I have calculated the occurrence of each element below
flat = [i for sub in lst for i in sub] #Group A will be lst[0] and so on
tmp = Counter(flat)
counts = Counter(tmp.values())
counts
Output: Counter({1: 3, 2: 2, 3: 1})
Now, I want to pull out the groups for elements that occur more than once, i.e. 2 will correspond to Group A and Group B. I am thinking of writing a for loop to check occurrence of each qualified element for all the groups, but this seems inefficient.
It sounds like you want a list of groups for each element, instead of just a count of appearances.
So, you obviously can't just use a Counter, because that explicitly maps values to counts, not lists. But you can just use a dict.
And you also obviously can't flatten the list before building the dict, because that throws away the group information that you wanted to store.
And meanwhile, don't worry about trying to write the whole thing as a one-liner. Write something that you can understand first, and then you can see if you can condense it once it's working.
So:
groupmapping = {}
for i, group in enumerate(lst):
for elem in group:
groupmapping.setdefault(element, list()).append(i)
… or:
groupmapping = defaultdict(list)
for i, group in enumerate(lst):
for elem in group:
groupmapping[element].append(i)
If you plan to use groupmapping as a normal dict that should raise KeyError instead of returning [] on a failed lookup, then do the first one, but here, it looks like you're just using it for this purpose, so a defaultdict makes more sense. (It'll also be a bit faster, if that matters.)
If your values can't be repeated within a group—or if they can, but you want to ignore that and collapse all appearances within a group—just replace the list with set and the append with add.
If you wanted names for the groups instead of indices, you must have those names somewhere, e.g., names = ['Group A', 'Group B', 'Group C']. If so, just replace enumerate(list) with zip(names, list).
Now, to get the groups of every repeated element:
for value, groups in groupmapping.items():
if len(groups) > 1:
print(f'{value} appears multiple times, in groups {groups}')
This is fine for efficiency. Sure, that second loop takes linear time O(M) in the number of distinct elements, but your original loop (whether hidden inside a Counter call or written out explicitly) already takes linear time O(N) in the number of total elements, and O(N+M) where M < N is just O(N).
And, more to the point, you obviously can't beat O(M) for any process that generates a sequence of M values.
You still need to iterate over your groups at least once to figure out if there is an element in them. For exceptionally large groups and multiple lookups it might be beneficial to turn them into sets and then check for an element instead of iterating through them (as iteration is much slower once on the Python side of things), but that's as far as you can take it. There is no need to count the rest of the elements, either, if you're only interested in the presence of one.
So, a simple function:
def get_groups(src, contains, minimum=2):
res = [x for x in src if contains in x]
if len(res) >= minimum:
return res
Should be more than you need. You can then use it as:
c = [[1, 2, 3], [1, 2], [1]] # etc.
print(get_groups(c, 2)) # [[1, 2, 3], [1, 2]]
print(get_groups(c, 3)) # None
print(get_groups(c, 2, 3)) # None
print(get_groups(c, 1, 3)) # [[1, 2, 3], [1, 2], [1]]

Store more than 1 value in python array? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I would like to store more than 1 value in a python array(I am open to any other data structure too).
For example :
array[1][2][3] = 1 # (this is what I am able to do now)
But later I also get the value 2, now instead of storing it in another array using the same indices, I want to be able to do this :
array[1][2][3] = 1,2
But I dont want to concatenate the existing result like in a string, and split the string to get the individual values.
Is there a way of doing this without having to introduce another dimension to the array?
edit : I want a neater way to store 2 values in the same cell.
Thanks
I would use defaultdict for this:
from collections import defaultdict
array = defaultdict(list)
array[(1,2,3)].append(1)
array[(1,2,3)].append(2)
Now array at position (1,2,3) is a list containing 1 and 2
If understand correctly, you can store new list with values you need in array[1][2][3] instead of single value:
array[1][2][3] = [1] # instead of = 1
array[1][2][3].append(2) # now it's [1, 2]
array[1][2][3].extend([3,4]) # now it's [1, 2, 3, 4]
all_values = array[1][2][3] # no another dimensions uses to get values
If you know all the contents a priori you may use a tuple. Here I will create pairs of numbers (n, n+1) and store them in a list:
>>> l = [(n,n+1) for n in xrange(0,4)]
>>> l
[(0, 1), (1, 2), (2, 3), (3, 4)]
If you decide you want to append another value, you can. Assume you want to append 3 to the tuple (1,2):
>>> l[1] = l[1] + (3,)
>>> l
[(0, 1), (1, 2, 3), (2, 3), (3, 4)]
Tuples are immutable, so they're faster than lists for construction, but you can't make changes to an instantiated tuple - you must replace it. If you're fairly certain your data won't change, use a tuple. If it will (and often), use a list.
Edit
If you want the values from the tuple, you can do the following:
>>> tup = l[0]
>>> tup
(0, 1)
>>> x, y = tup
>>> x
0
>>> y
1
>>> t, u = l[2] # alternatively
>>> t
2
>>> u
3
array[1][2][3] = 1,2
Seems like you want to have a list in array[1][2][3], which you could actually do with
array[1][2][3] = [1,2]
or alternatively, as already mentionned by others with variations of
array[1][2][3] = []
array[1][2][3].append(1)
array[1][2][3].extend([2])
Mind the fact that use of t-uples is also possible
array[1][2][3] = (1,2)
But in this case, you won't be able to extend your "list" nor to modify its content (t-uples are indeed constant arrays, in size as well as in content.).
Is there a way of doing this without having to introduce another
dimension to the array?
Well... this requirement seems rather antagonistic with your previous one.
array[1][2][3] = 1,2
suggests that your are able to differentiate between "array[1][2][3][0]" (=1) and "array[1][2][3][1]" (=2). So, unless I don't understand your question, the short answer is "no" :)

Categories

Resources