3

I need to calculate pressure fluctuations p (the code for this is working already good); but I also need to store the values of p at the different time positions so that I have a function p(t) and can plot it later.

The problem is: the values of t are floats. The list with t-values looks like this:

t = [88.386, 88.986, 90.386, ...]

and some of these values also appears multiple times, which means, if p(t=88.986) is calculated more than once, the both values just need to be added up.

How can I handle this?

I would appreciate any help.

  • Why is it a problem that they are floats? You can add floats to lists, no problem there. – Christian W. Dec 09 '16 at 10:36
  • And how can I access the value `p` at the time `1.5`? I know only `p[int]` but not `p[float]` –  Dec 09 '16 at 10:39
  • I dont need to add something to the list with floats. I need to store the data at the "position" of 88.386 and so on –  Dec 09 '16 at 10:40
  • 1
    Well then `dict` would be a better choice. – Christian W. Dec 09 '16 at 10:40
  • Is this possible to solve the problem with lists anyway? –  Dec 09 '16 at 10:43
  • I would have post an answer using [`lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache), but unfortunately it's [not possible](http://stackoverflow.com/a/15587418/3077939) to access the cache this way. Then, best answer is probably [this one](http://stackoverflow.com/a/41058577/3077939), mimic of the lru_cache but with proper access to the cache. – aluriak Dec 09 '16 at 10:55

3 Answers3

1

You can use a decorator to wrap your function and cache the values in a proper way.

In [39]: from functools import wraps

In [40]: from collections import defaultdict

In [41]: cache = defaultdict(float) 

In [42]: def cache_value(f):
   ....:         global cache
   ....:         @wraps(f)
   ....:         def wrapped(n):
   ....:                 result = f(n)
   ....:                 cache[n] += result
   ....:                 return result
   ....:         return wrapped

Here the defaultdict will add a new item to the cache if it doesn't exist in dictionary already, otherwise will sum up the new value with the previous one.

Demo:

In [43]: @cache_value
   ....: def p(n):
   ....:     return 2
   ....: 

In [44]: 

In [44]: p(6.33)
Out[44]: 2

In [45]: p(6.33)
Out[45]: 2

In [46]: p(4.15)
Out[46]: 2

In [47]: p(5.07)
Out[47]: 2

In [48]: cache
Out[48]: defaultdict(<class 'float'>, {4.15: 2.0, 5.07: 2.0, 6.33: 4.0})
Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • As a side note, you should make sure that the p values are rounded to an acceptable number of digits, in order to get the cache working properly. – aluriak Dec 09 '16 at 10:57
  • @aluriak Good note, but it depends on OP's intent that wants to consider let say `2.33` and `2.3333` as one key. – Mazdak Dec 09 '16 at 11:48
1

From your answers; you want to use position as key, and have some value for that. That basically means you want to use a dict instead of list. You can assign values to dictionary by saying dict_time[key] = value. An example:

dict_time = {}
dict_time[0.1] = 2
print(dict_time[0.1])
//2

to sum up to the value if value exists you could check if they key is already in dict and then sum it if it exists, and otherwise just add it.:

if key in dict_time:
   dict_time[key] += value
else:
   dict_time[key] = value

Or you could use defaultdict as suggested by kasramvd, in that case you can just use += without checking if they key exists.

Later on you can access the value by asking dict_time[key]:

>>> dict_time[0.1]
1
Christian W.
  • 2,532
  • 1
  • 19
  • 31
1

If you want to keep using lists, you can use sets to get all unique time values and them sum up all the pressures elements for that time. The pressure value will be stored in the correspondent index for the first registered repetition of that time value:

p = [3, 5, 6, 5]
t = [88.386, 88.986, 90.386, 88.386]

# the added presures will be stored in this list
new_pressures = []
# get all the different time values
unique_times = set(t)

#Create new null element in list for every unique time
for value in unique_times:
    new_pressures.append(0)
    for index, item in enumerate(t):
        if item == value:
            #add to the pressure value every time coincidence index
            new_pressures[-1] += p[index]
print new_pressures

The output of the function results in:

[8, 5, 6]
Jalo
  • 1,131
  • 1
  • 12
  • 28
  • Thanks a lot! This possibility using a set is actually the best for my case. –  Dec 12 '16 at 14:16