I have a set of datapoints such as (THIS IS AN EXAMPLE)
val=4; (*this value is calculated before in the program, so it not known a priori*)
x={0,1,2,3};
data=Table[0, {val}];
data[[1]] = {1,5,6,8};
data[[2]] = {9,7,1,3};
data[[3]] = {3,4,5,6};
data[[4]] = {2,2,4,6};
Now I can plot each of these data with ListPlot as
ListPlot[Transpose[{x,data[[1]]}]]
and if I want to plot more than one I can do
ListPlot[{Transpose[{x, data[[1]]}], Transpose[{x, data[[2]]}]}]
but how can I plot all of them in one code single line, by considering that val is calculated before in the program?
Is there a way to do something like
For[i = 1, i < val + 1, i++, ListPlot[Transpose[{x,data[i]}]]......]
having a single graph with all x-y curves?
Indeed I would like a static picture of
Manipulate[ListPlot[Transpose[{x, data[[i]]}]], {i, 1, val,1}]
Thanks
Virgilio
You want to "do the same thing" to every element of a list. That should tell you to think of using Map. Your list is named data and each element is your four element sublist. If you look at the help page for Map it shows you need to think up a function that does what you need to do to each individual sublist. You have already understood that you need to use Transpose with x and your sublist so that tells you your function and you are almost there. The result of Map will be a list of all those results. So
In[1]:= x = {0, 1, 2, 3};
data = {{1, 5, 6, 8}, {9, 7, 1, 3}, {3, 4, 5, 6}, {2, 2, 4, 6}};
ListPlot[Map[Transpose[{x, #}] &, data], Joined -> True]
Out[3]= ...FourOverlaidPlotsSnipped...
Go through that a word at a time until you can really understand the thinking that was done to be able to write that. You will use this idea again and again if you keep using Mathematica.
For the example you give the cleanest method is to use DataRange:
data = {{1, 5, 6, 8}, {9, 7, 1, 3}, {3, 4, 5, 6}, {2, 2, 4, 6}};
ListLinePlot[data, DataRange -> {0, 3}]
Please ask your future questions on the dedicated Mathematica StackExchange site:
Related
Let's say I have a vector, the values are from 1 to 10. I want that if you find 5 and 5 next to each other, remove them together with the next elements.
input
[1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10]
expected output
[1, 2, 3, 4]
This was my attempt. I'm finding index to remove, but borrowing rules are making me stuck.
let mut element = vec![1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10];
for (index, val) in element.iter().enumerate() {
if *val == 5 {
if let Some(next_val) = element.get(index + 1) {
if *next_val == 5 {
//element.drain(index..);
}
}
}
}
Rust is saving you from iterator invalidation (a common source of bugs in other languages). This is an error that usually happens when you try to modify a data structure while concurrently iterating over it. You cannot move on to the (now-deleted) next element after calling element.drain(index..). So you need to add a break after that point to avoid memory unsafety.
In this case just adding break; is sufficient to make the code compile. However, for a more concise, linear solution, take full advantage of the iterators and methods provided by the standard library:
if let Some(index) = element.windows(2).position(|pair| pair[0] == pair[1]) {
element.truncate(index);
}
windows(2) on a slice gives an iterator over subslices of length 2, and the position call returns the index of the first element of that iterator for which the two elements of the slice are equal. (If no such pair exists, position returns None.)
I find that the position closure becomes more obvious with the (currently unstable) array_windows feature:
if let Some(index) = element.array_windows().position(|[x, y]| x == y) {
element.truncate(index);
}
Playground
Related
is it possible to filter on a vector in-place?
You can't do what you want to do because you want to remove some elements from a vector while you are iterating it. And this is a big mistake. Note that removing any elements from a vector invalidates the iterators, hence you will access unexpected locations so rust doesn't allow UBs
You can use something like the following
let mut elements = vec![1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10];
let mut first_repeated_five_index_op = None;
for index in 0..elements.len()-1{
if elements[index] == 5 && elements[index + 1] == 5{
first_repeated_five_index_op = Some(index);
break;
}
}
if let Some(first_repeated_five_index) = first_repeated_five_index_op{
elements.truncate(first_repeated_five_index);
}
println!("{:?}", elements);
See a Demo
I'm implementing a function where I'll be repeatedly eliminating values from a large list, and passing a copy of this list as a vector into another function each iteration:
let mut v = vec![5, 4, 4, 2, 6, 5, 1, 8, 2, 1, 6, 5, 4, 2, 0, 1];
for i in 0..10 {
println!("{}", Vector::from(v).iter().sum());
v.retain(|x| x > i);
}
If v is very large, this will be slow. Is there a better way? I tried:
let mut v = vec![5, 4, 4, 2, 6, 5, 1, 8, 2, 1, 6, 5, 4, 2, 0, 1];
let mut v = v.into_iter().map(|x| Some(x)).collect();
(and then replace the "deleted" values with None) but this just seemed unwieldy to convert to and from an ordinary Vec.
How should I be storing this list of values?
You can restructure your creation of the copied list to do the removal before the copy:
for i in 0..10 {
let dup = your_list.iter().filter(|n| n > i).collect::<Vec<_>>();
use_it(dup);
}
If it is important to your use case that you are left with a filtered Vec, and cannot change the collection type, then this is probably the most useful means. If the filters are cumulative, you can overwrite the original Vec with the filtered Vec each iteration to reduce the workload for each future iteration.
let mut list = your_list;
for i in 0..10 {
list = list.iter().filter(|n| n > i).collect();
use_it(list.clone());
}
The question you asked is directly answered by reshaping how you filter and duplicate the vector, but if you are able to change your types, then the answers below may be more worthwhile.
If your use_it function does not require a Vec or slice, then you may be better served by restructuring the consumer to take an iterator of numbers, and passing in your_list.iter().filter(...). This will result in no copying or rearranging in memory, and the consumer function will just skip the invalid values.
If you care more about counting how many times numbers appear in a collection, and do not specifically need a sequential list in memory, you can rearrange your list into a HashMap:
use std::collections::HashMap;
let mut dict: HashMap<i32, usize> = HashMap::new();
for num in your_list {
*dict.entry(num).or_insert(0) += 1;
}
and then you can filter numbers out of the map with constant-time access rather than linear-time in the size of the collection.
Since this is a question about performance, then you will need to benchmark everything so that you can test your assumptions. That being said and unless there's something smart to do inside the function you call (maybe only copying lazily the items you want to mutate), then I think your retain+clone approach is close to the fastest you can do. Using Options is almost certainly a bad idea: it adds checks everywhere and it kills cache locality.
The only thing that may improve performance is to do the copy and filtering in a single pass:
let mut v = vec![5, 4, 4, 2, 6, 5, 1, 8, 2, 1, 6, 5, 4, 2, 0, 1];
let mut work = v.clone();
for i in 0..10 {
println!("{}", work.iter().sum::<i32>());
work.clear();
v.retain(|&x| if (x > i) { work.push (x); true } else { false });
}
playground
Note that this will probably not make any difference if your data fits in the cache. In any case, benchmark, benchmark, benchmark! Lots of assumptions get proven wrong in the face of compiler optimizations and modern CPU architecture.
If you're removing the elements in order you should consider a queue. Using remove() takes O(1) time to remove an element, because it is essentially a dequeue or a pop.
Is there a Qore operator/function to get sublist from a list without modifying source list, i.e. equivalent of substr(). extract operator removes items from original list.
list l = (1,2,3,4,5,6,7,8,9);
list l2 = extract l, 2, 4;
printf("l:%y\nl2:%y\n", l, l2);
l:[1, 2, 7, 8, 9]
l2:[3, 4, 5, 6]
select operator supports in condition argument $# macro expanded as index.
list l = (1,2,3,4,5,6,7,8,9);
list l2 = select l, $# >= 2 && $# <2+4;
printf("l:%y\nl2:%y\n", l, l2);
l:[1, 2, 3, 4, 5, 6, 7, 8, 9]
l2:[3, 4, 5, 6]
The select operator is the best solution as you stated in your answer to your own question.
The splice and extract operators both will modify the list operand, which is not what you want.
Note that there is an outstanding feature issue for this in Qore (1781) - not yet targeted to a release, but it could go in the next major release (0.8.13) if there is any interest.
I am new to Prolog and came across this practice excercise. The question asks to define a predicate
zipper([[List1,List2]], Zippered). //this is two lists within one list.
This predicate should interleave elements of List1 with elements of List2.
For example,
zipper([[1,3,5,7], [2,4,6,8]], Zippered) -> Zippered = [1,2,3,4,5,6,7,8].
zipper([[1,3,5], [2,4,6,7,8]], Zippered) -> Zippered = [1,2,3,4,5,6,7,8].
So far I have a solution for two different list:
zipper ([],[],Z).
zipper([X],[],[X]).
zipper([],[Y],[Y]).
zipper([X|List1],[Y|List2],[X,Y|List]) :- zipper(List1,List2,List).
I am not sure how I can translate this solution for one list. Any suggestion on where I can start would be greatly helpful!
Firstly you should change zipper ([],[],Z). to zipper ([],[],[]).. Then to make it work for one list you could do what mat recommended in the comment or you could change it a little. So my version is:
zipper([],[],[]).
zipper([X,[]],X).
zipper([[],Y],Y).
zipper([[X|List1],[Y|List2]],[X,Y|List]) :- zipper([List1,List2],List).
And for your examples:
?- zipper([[1,3,5,7], [2,4,6,8]], Zippered).
Zippered = [1, 2, 3, 4, 5, 6, 7, 8] ;
Zippered = [1, 2, 3, 4, 5, 6, 7, 8] ;
false.
?- zipper([[1,3,5],[2,4,6,7,8]],Zippered).
Zippered = [1, 2, 3, 4, 5, 6, 7, 8] ;
false.
Suppose I have a tuple of (1, 2, 3) and want to index a multidimensional array with it such as:
index = (1, 2, 3)
table[index] = 42 # behaves like table[1][2][3]
index has an unknown number of dimensions, so I can't do:
table[index[0]][index[1]][index[2]]
I know I could do something like this:
functools.reduce(lambda x, y: x[y], index, table)
but it's utterly ugly (and maybe also inefficient), so I wonder if there's a better, more Pythonic choice.
EDIT: Maybe a simple loop is best choice:
elem = table
for i in index:
elem = elem[i]
EDIT2: Actually, there's a problem with both solutions: I can't assign a value to the indexed array :-(, back to ugly:
elem = table
for i in index[:-1]:
elem = elem[i]
elem[index[-1]] = 42
The question is very interesting and also your suggested solution looks good (havn't checked it, but this kind of problem requires a recursive treatment and you just did it in one line).
However, the pythonic way I use in my programs is to use dictionaries of tuples. The syntax is array-like, the performance - of a dictionary, and there was no problem in it for me.
For example:
a = {(1, 2, 3): 'A', (3, 4, 5): 'B', (5, 6, 7, 8): 'C'}
print a[1, 2, 3]
print a[5, 6, 7, 8]
Will output:
A
B
And assigning to an index is super easy:
a[1, 4, 5] = 42. (But you might want to first check that (1, 4, 5) is within the dict, or else it will be created by the assignment)