Assuming I have a list, is there a built-in operator or function to select elements based on a list of indices?
For example, an operator something like this ["a", "b", "z"] = alphabet[0, 1, 25]
An naive implementation of this could be:
def select(list, indices) do
Enum.map(indices, &(Enum.at(list, &1)))
end
If it doesn't exist, it this a deliberate omission to avoid lists being treated like arrays?
An example of what I'm attempting that made me want this, in case I'm asking the wrong question: Given a list, I want to select the first, middle, and last elements, then calculate the median of the three. I was doing length(list) to calculate the length, then I wanted to use this operator/function to select the three elements I'm interested in.
As far as I know, the built in operator does not exist. And each time I have to fetch several elements in a list, I use the same implementation as yours. It is quite short and simple to recreate and I suspect it is the reason why there are no off-the shelf solution in elixir.
Another reason I can think of, is as you pointed out, the fact that lists aren't arrays: when you want to access one element, you have to access all the elements before it, therefore accessing elements by a list of index is not a relevant function, because list are not optimized to be used that way.
Still I often access a list of element with a list of index, meaning that I might not be using elixir the right way.
Related
I'm doing this exercise for which I have to write a predicate randomnames/1 for generating a random list of three names (no duplicates allowed). I have a database with 10 names in it already and they all correspond to a number, for example: name(1, Mary).
I wrote a predicate for generating one random name:
randomname(Name) :-
random(0, 11, N), % generate random integer between 1 and 10.
name(N, Name).
My question would be: How do I get this in a list? And a list of exactly three elements at that?
I don't want to use too many built-ins. length/2 would be alright though. I think I might need it :)
Thanks a lot!
Edit: I figured I would first try to generate a list of three random numbers (the names can come later). I wrote this horribly wrong little thing:
numberlist([N|T]) :-
random(0, 11, N),
length([N|T], 3),
numberlist(T).
I know how to do this with a /2 predicate; when the user can just enter in the query that they want a list with three elements (numberlist(3,X).for example). But I'm can't seem to figure out how to write down in code that I always want a list of three numbers.
I was also thinking of using findall for generating my list, but again I don't know how to limit the length of the list to three random elements.
When describing lists in Prolog, it is often useful to first describe how a single element looks like.
For example, in your case, it seems you already have a predicate like random_name/1, and it describes a single element of the list you want to describe.
So, to describe a list consisting of three such elements, what about:
random_names([A,B,C]) :-
random_name(A),
random_name(B),
random_name(C).
This describes a list with three elements, and random_name/1 holds for each of these elements.
Forgive me if this question is dumb, but it occurred to me I don't know how a language knows a list is sorted or not.
Say I have a list:
["Apple","Apricot","Blueberry","Cardamom","Cumin"]
and I want to insert "Cinnamon".
AFAIK The language I'm using doesn't know the list is sorted; it's just a list. And it doesn't have a "wide screen" field of view like we do, so it doesn't know where the A-chunk ends and the C-chunk begins from outside the list. So it goes through and compares the first letter of each array string to the first letter of the insert string. If the insert char is greater, it moves to the next string. If the chars match, it moves to the next letter. If it moves on to the next string and the array's char is greater than the insert's char, then the char is inserted there.
My question is, can a language KNOW when a list is sorted?
If the process for combing through a unsorted and sorted list is the same, and the list is still iterated through, then how does sorting save time?
EDIT:
I understand that "sorting allows algorithms that rely on sorting to work"; I apologize for not making that clear. I guess I'm asking if there's anything intrinsic about sorting inside computer languages, or if it's a strategy that people built on top of it. I think it's the latter and you guys have confirmed it. A language doesn't know if it's sorting something or not, but we recognize the performance difference.
Here's the key. The language doesn't / can't / shouldn't know whether your data structure is sorted or unsorted. In fact it doesn't even care what data structure it really is.
Now consider this: What does insertion or deletion really mean? What exact steps need to be taken to insert a new item or delete an existing one. It turns out that the exact meaning of these operations depend upon the data structure that you're using. An array will insert a new element very differently than a linked list.
So it stands to reason that these operations must be defined in the context of the data structure on which these are being applied. The language in general does not supply any keywords to deal with these data structures. Rather the accompanying libraries provide built-in implementations of these structures that contain methods to perform these operations.
Now to the original question: How does the language "know" if a list is sorted or not and why is it more efficient to deal with sorted lists? The answer is, as evident from what I said above, the language doesn't and shouldn't know about the internals of a list. It is the implementation of the list structure that you're using that knows if it is sorted or not, and how to insert a new node in an ordered manner. For example, a certain data structure may use an index (much like the index of a book) to locate the position of the words starting with a certain letter, thus reducing the amount of time that an unsorted list would require to traverse through the entire list, one element at a time.
Hope this makes it a bit clearer.
Languages don't know such things.
Some programming languages come with a standard library containing data structures, and if they don't, you generally can link to libraries that do.
Some of those data structures may be collection types that maintain order.
So given you have a data structure that represents an ordered collection type, then it is that data structure that maintains the order of the collection, whenever an item is added or removed.
If you're using the most basic collection type, an array, then neither the language nor the runtime nor the data structure itself (the array) care in the slightest at what point you insert an item.
can a language KNOW when a list is sorted
Do you mean a language interpreter? Of course it can check whether a list is sorted, simply by checking each elements is "larger" than the previous. I doubt that interpreters do this; why should they care if the list is sorted or not?
In general, if you want to insert "Cinammon" into your list, you need to either specify where to insert it, or just append it at the end. It doesn't matter to the interpreter if the list is sorted beforehand or not. It's how you use the list that determines whether a sorted list will remain sorted, and whether or not it needs to be sorted to begin with. (For example, if you try to find something in the list using a binary search, then the list must be sorted. But you must arrange for this to be the case).
AFAIK The language I'm using ...
(which is?)
... doesn't know the list is sorted; it's just a list. And it doesn't have a "wide screen" field of view like we do, so it doesn't know where the A-chunk ends and the C-chunk begins from outside the list. So it goes through and compares the first letter of each array string to the first letter of the insert string. If the insert char is greater, it moves to the next string. If the chars match, it moves to the next letter. If it moves on to the next string and the array's char is greater than the insert's char, then the char is inserted there.
What you're saying, I think, is that it looks for the first element that is "bigger than" the one being inserted, and inserts the new element just before it. That implies that it maintains the "sorted" property of the list, if it is already sorted. This is horribly inefficient for the case of unsorted lists. Also, the technique you describe for finding the insertion point (linear search) would be inefficient, if that is truly what is happening. I would suspect that your understanding of the list/language semantics are not correct.
It would help a lot if you gave a concrete example in a specific language.
I have the following problem and would like to see if somebody could tell me if I'm on the right track with my approach:
I want to do a "rolling window" kind of computation on two linked lists and for that I need them to be sorted by magnitude. If I just have one linked list, writing the corresponding mergesort is not the problem. However, now I'm wondering how I should go about the fact that I have two linked lists where I want to have the corresponding elements from list 1 and list 2 move together as I sort by the magnitude of list 1. If this is not entirely clear, this is what I mean:
In list 1, I want to do a sort by magnitude, so basically just rearrange the pointers. Whenever I move element "n" in one list, however, I also need to move the corresponding element "n" in the other list to the same position as the element from the other one.
Would my approach of using mergesort for this be the right way to go or does anyone know a better approach? I am having a hard time imagining how I would go about reordering the second list while mergesorting the first one since the second list is not necessarily going to be sorted by magnitude anymore and I need the individual elements to correspond to each other.
Thanks!
Marc
Just create a list of pairs of corresponding elements, and then sort the list by the first element of the pair.
I'm trying to make a tracking algorithm, for this I need to constantly get the position of all the elements in the list, I want to know if there is a way to do it in a single line without a "ForEach", I know you can copy one whole list to another list, that is what I am doing right now.
I have this:
List copy = List original;
But I want to do something like this
List copy = List original.Position
Note: position is a vector2 var inside my list.
I would recommend using Linq:
List<Position> copy = original.Select(e => e.Position).ToList();
'e' I randomly chose, e stands for element. It represents each element in the list. This is the equivalent to:
List<Position> copy = new List<Position>();
foreach(Element e in original)
{
copy.Add(e.Position);
}
This will return a List<Position>. Be aware that this List won't be of the same type as the original.
Also note that Linq queries, whilst clean, concise and easy to read, aren't as efficient as manually looping. However for a small list, a couple of hundred or less, you won't see any difference.
Here is a link to a very in depth SO question on this topic: foreach + break vs linq FirstOrDefault performance difference
And here is a link to using linq queries: http://msdn.microsoft.com/en-us/library/bb397906.aspx
In the example in the last link (to MSDN) you will see two forms of linq notation. One is the standard notation as I have used. The other is query form, which is similar to calling Where() using the standard notation. I find the query notation similar to writing SQL queries.
One final note is that you can also produce an array using ToArray() instead of ToList(). Preferable if the copy will be of a fixed size and you are going to randomly access them. Regardless of which you use, you can rely on the order of the copy to be the same as the original and that's how you should relate it to the original, so the 4th Position in copy is the Position of the 4th element in original for example.
I hope this has helped.
let's say we have a list of elements:
[(a,b); (c,d); (e,f)]
What function would check if element (lets say A, where A=(x,y)) is in the list or not?
Use List.mem to do the search for a match.
let a = (3,4)
List.mem a [(1,2); (3,4); (5,6)]
You can also use List.memq if you want to check if the two items both reference the same entity in memory.
Here's a hint on how to write this yourself. The natural way to to process a list is to initially look at the first element, then check the remainder of the list recursively until you have an empty list. For this problem, you could state the algorithm in English as follows:
If the list is empty then the item is not in the list,
else if the first list element equals the item then it is in,
else it is the answer to (Is the item in the remainder of the list?)
Now you just need to translate this into OCaml code (using a recursive function).
In general, if you can describe what you want to do in terms of smaller or simpler parts of the problem, then writing the recursive code is straightforward (although you have to be careful the base cases are correct). When using a list or tree-structured data the way to decompose the problem is usually obvious.