Related
list.append() appends to the end of a list. This explains that list.prepend() does not exist due to performance concerns for large lists. For a short list, how do I prepend a value?
The s.insert(0, x) form is the most common.
Whenever you see it though, it may be time to consider using a collections.deque instead of a list. Prepending to a deque runs in constant time. Prepending to a list runs in linear time.
This creates a new list with x prepended to it, rather than modifying an existing list:
new_list = [x] + old_list
What's the idiomatic syntax for prepending to a short python list?
You don't usually want to repetitively prepend to a list in Python.
If the list is short, and you're not doing it a lot... then ok.
list.insert
The list.insert can be used this way.
list.insert(0, x)
But this is inefficient, because in Python, a list is an array of pointers, and Python must now take every pointer in the list and move it down by one to insert the pointer to your object in the first slot, so this is really only efficient for rather short lists, as you ask.
Here's a snippet from the CPython source where this is implemented - and as you can see, we start at the end of the array and move everything down by one for every insertion:
for (i = n; --i >= where; )
items[i+1] = items[i];
If you want a container/list that's efficient at prepending elements, you want a linked list. Python has a doubly linked list, which can insert at the beginning and end quickly - it's called a deque.
deque.appendleft
A collections.deque has many of the methods of a list. list.sort is an exception, making deque definitively not entirely Liskov substitutable for list.
>>> set(dir(list)) - set(dir(deque))
{'sort'}
The deque also has an appendleft method (as well as popleft). The deque is a double-ended queue and a doubly-linked list - no matter the length, it always takes the same amount of time to preprend something. In big O notation, O(1) versus the O(n) time for lists. Here's the usage:
>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])
deque.extendleft
Also relevant is the deque's extendleft method, which iteratively prepends:
>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])
Note that each element will be prepended one at a time, thus effectively reversing their order.
Performance of list versus deque
First we setup with some iterative prepending:
import timeit
from collections import deque
def list_insert_0(prepends: int):
l = []
for i in range(prepends):
l.insert(0, i)
def list_slice_insert(prepends):
l = []
for i in range(prepends):
l[:0] = [i] # semantically same as list.insert(0, i)
def list_add(prepends):
l = []
for i in range(prepends):
l = [i] + l # caveat: new list each time
def deque_appendleft(prepends):
d = deque()
for i in range(prepends):
d.appendleft(i) # semantically same as list.insert(0, i)
def deque_extendleft(prepends):
d = deque()
d.extendleft(range(prepends)) # semantically same as deque_appendleft above
And a function for analysis, so that we can fairly compare all operations across a range of usages:
def compare_prepends(n, runs_per_trial):
results = {}
for function in (
list_insert_0, list_slice_insert,
list_add, deque_appendleft, deque_extendleft,
):
shortest_time = min(timeit.repeat(
lambda: function(n), number=runs_per_trial))
results[function.__name__] = shortest_time
ranked_methods = sorted(results.items(), key=lambda kv: kv[1])
for name, duration in ranked_methods:
print(f'{name} took {duration} seconds')
and performance (adjusting the number of runs per trial down to compensate for longer running times of more prepends - repeat does three trials by default):
compare_prepends(20, 1_000_000)
compare_prepends(100, 100_000)
compare_prepends(500, 100_000)
compare_prepends(2500, 10_000)
>>> compare_prepends(20, 1_000_000)
deque_extendleft took 0.6490256823599339 seconds
deque_appendleft took 1.4702797569334507 seconds
list_insert_0 took 1.9417422469705343 seconds
list_add took 2.7092894352972507 seconds
list_slice_insert took 3.1809083241969347 seconds
>>> compare_prepends(100, 100_000)
deque_extendleft took 0.1177942156791687 seconds
deque_appendleft took 0.5385235995054245 seconds
list_insert_0 took 0.9471780974417925 seconds
list_slice_insert took 1.4850486349314451 seconds
list_add took 2.1660344172269106 seconds
>>> compare_prepends(500, 100_000)
deque_extendleft took 0.7309095915406942 seconds
deque_appendleft took 2.895373275503516 seconds
list_slice_insert took 8.782583676278591 seconds
list_insert_0 took 8.931685039773583 seconds
list_add took 30.113558700308204 seconds
>>> compare_prepends(2500, 10_000)
deque_extendleft took 0.4839253816753626 seconds
deque_appendleft took 1.5615574326366186 seconds
list_slice_insert took 6.712615916505456 seconds
list_insert_0 took 13.894083382561803 seconds
list_add took 72.1727528590709 seconds
The deque is much faster. As the lists get longer, deques perform even better. If you can use deque's extendleft you'll probably get the best performance that way.
If you must use lists, keep in mind that for small lists, list.insert works faster, but for larger lists, inserting using slice notation becomes faster.
Don't prepend to lists
Lists were meant to be appended to, not prepended to. If you have a situation where this kind of prepending is a hurting the performace of your code, either switch to a deque or, if you can reverse your semantics and accomplish the same goal, reverse your list and append instead.
In general, avoid prepending to the built-in Python list object.
If someone finds this question like me, here are my performance tests of proposed methods:
Python 2.7.8
In [1]: %timeit ([1]*1000000).insert(0, 0)
100 loops, best of 3: 4.62 ms per loop
In [2]: %timeit ([1]*1000000)[0:0] = [0]
100 loops, best of 3: 4.55 ms per loop
In [3]: %timeit [0] + [1]*1000000
100 loops, best of 3: 8.04 ms per loop
As you can see, insert and slice assignment are as almost twice as fast than explicit adding and are very close in results. As Raymond Hettinger noted insert is more common option and I, personally prefer this way to prepend to list.
In my opinion, the most elegant and idiomatic way of prepending an element or list to another list, in Python, is using the expansion operator * (also called unpacking operator),
# Initial list
l = [4, 5, 6]
# Modification
l = [1, 2, 3, *l]
Where the resulting list after the modification is [1, 2, 3, 4, 5, 6]
I also like simply combining two lists with the operator +, as shown,
# Prepends [1, 2, 3] to l
l = [1, 2, 3] + l
# Prepends element 42 to l
l = [42] + l
I don't like the other common approach, l.insert(0, value), as it requires a magic number. Moreover, insert() only allows prepending a single element, however the approach above has the same syntax for prepending a single element or multiple elements.
Lets go over 4 methods
Using insert()
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l.insert(0, 5)
>>> l
[5, 0, 1, 2, 3, 4]
>>>
Using [] and +
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l = [5] + l
>>> l
[5, 0, 1, 2, 3, 4]
>>>
Using Slicing
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l[:0] = [5]
>>> l
[5, 0, 1, 2, 3, 4]
>>>
Using collections.deque.appendleft()
>>>
>>> from collections import deque
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l = deque(l)
>>> l.appendleft(5)
>>> l = list(l)
>>> l
[5, 0, 1, 2, 3, 4]
>>>
I would have done something quite fast forward in python >= 3.0
list=[0,*list]
It maybe be not the most efficient way, but it's the most Pythonic in my opinion.
I need a rock solid RegExp to try and solve some issue with Raphael.js parseStringPath processing regarding Arc path commands and possible others (SnapSVG also inherits the problem). You see, arcTo path command accepts 7 coordinates and settings, but some strings might be malformed due to extreme optimization and the browser doesn't flag them, rather renders them properly. Check Raphael.js demo here.
Have a look at this example, I'm using the RegExp from Raphael.js and a very simplistic example with my own RegExp called incorrectReg, trying to break strings like 000 into [0,0,0] or 011 into [0,1,1].
let spaces = "\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029",
pathValues = new RegExp(`(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[${spaces}]*,?[${spaces}]*`, `ig`),
incorectReg = new RegExp(`([${spaces}]*0(?=[a-z0-9])|([${spaces}]\\0)*0(?=[a-z0-9]*))`, `ig`); // THIS ONE
function action(){
let input = document.getElementById('input'),
output = document.getElementById('output'),
pathValue = input.getAttribute('d'),
segments = pathValue.replace(/([a-z])/gi,'|$1').split('|').filter(x=>x.trim()),
pathArray = []
segments.map(x=>{
let pathCommand = x[0],
pathParams = x.replace(pathCommand,'').trim()
pathArray.push( [pathCommand].concat(
pathParams.replace(',',' ')
.replace(pathValues,' $1 ')
.replace(incorectReg,'$1 ')
.split(' '))
.filter(x=>x)
);
})
output.setAttribute('d',pathArray.map(x=>x.join(' ')).join(''))
console.table(pathArray)
}
svg {max-width:49%}
<button onclick="action()">Extract</button>
<hr>
<svg viewBox="0 0 16 16">
<path id="input" d="M2,0a2 2 0 00,-2 2a2 2 0 002 2a.5.5 0 011 0z" stroke="red" stroke-width="1px" fill="none"></path>
</svg>
<svg viewBox="0 0 16 16">
<path id="output" d="M0 0" stroke="green" stroke-width="1" fill="none"></path>
</svg>
As you can see in your browser console, we already solve the 000 group (which is obviously not a valid number, boolean, or anything specific), we just have to solve 011 and 11, where all these groups are in fact a string of booleans.
So again, the arcTo path command works with
arcTo -> ['A', rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y]
// str, float, float, float, boolean (0|1), boolean (0|1), float, float
I need a better incorrectReg RegExp and a combination of solutions to properly handle mainly arcTo, and other similar cases. Open to any suggestion.
Thank you
According to the discussion below OP, I propose not to use regexp, but rather a proper parser (or lexer or tokenizer or how to correctly call it).
You can
write your own parser (nice excercise)
use something existing, e.g. I have successfully tried
svg-path-parser.
I am not even sure if such "super"regexp is possible to create.. Anyway you can use "sub"regexp in the parsing process :-)
Just for clarity and serving the community, I will post a working solution, it might help somebody in the future.
Unfortunately the incorrectReg RegExp, good or bad cannot work because it can also change other values as well (EG: M0,11 returns ["M",0,1,1] with the RegExp provided by TheFourthBird), so yea Jan, you were right!
Here's a working solution, please feel free to edit or add more clarity if you like. Once we all agree on a rock solid solution, I will submit a PR to Raphael right after.
let spaces = "\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029",
pathValues = new RegExp(`(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[${spaces}]*,?[${spaces}]*`, `ig`),
incorrectReg = new RegExp(`(?<=[01${spaces}]+)([01])[${spaces}]*`, `g`); // FIXED ONE
function action(){
let input = document.getElementById('input'),
output = document.getElementById('output'),
pathValue = input.getAttribute('d'),
segments = pathValue.replace(/([a-z])/gi,'|$1').split('|').filter(x=>x.trim()),
pathArray = []
segments.map(x=>{
let pathCommand = x[0],
pathParams = x.replace(pathCommand,'').trim();
pathParams = pathParams.replace(',',' ')
.replace(pathValues,' $1 ')
/* .replace(incorrectReg,' $& ') */
.split(' ').filter(x=>x);
if ( pathCommand.toLowerCase() === 'a' && pathParams.length < 7){
for (let i=0, ln = pathParams.length; i<ln; i++){
if ( (i === 3 || i === 4) && pathParams[i].length > 1 ) {
pathParams = pathParams.slice(0,i) // first part of array
.concat(pathParams[i][0]) // extract largeArcFlag OR sweepFlag
.concat(
pathParams[i].slice(1).replace(/(\-\d|\-\.\d|\.\d*(?=\.))/g,'|$1').split('|'), // get sweepFlag
pathParams.slice(i+1)) // continue after flags
.filter(x=>x) // remove added empty "space" items
ln = pathParams.length // update length
}
}
if (pathParams.length === 7) {
pathArray.push([pathCommand].concat(pathParams.splice(0, 7)));
} else {
throw Error(`arcTo requires 7 coordinates, only ${pathParams.length + ' given: ['+pathParams.join(',')}]`)
}
} else {
pathArray.push( [pathCommand].concat(pathParams) );
}
})
output.setAttribute('d',pathArray.map(x=>x.join(' ')).join(''))
// console.log(pathArray)
}
svg {max-width:49%}
<button onclick="action()">Extract</button>
<hr>
<svg viewBox="0 0 16 16">
<path id="input" d="M2 0a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V2a2 2 0 00-2-2H2zm7.5 11h-4a.5.5 0 01-.5-.5v-4a.5.5 0 011 0v2.793l4.146-4.147a.5.5 0 01.708.708L6.707 10H9.5a.5.5 0 010 1z" fill="red"></path>
</svg>
<svg viewBox="0 0 16 16">
<path id="output" d="M0 0" fill="green"></path>
</svg>
This question already has answers here:
find the only unpaired element in the array
(10 answers)
What are bitwise operators?
(9 answers)
What do these JavaScript bitwise operators do?
(3 answers)
Closed 5 years ago.
Saw an interesting piece of code to find a lonely number in a list of duplicate numbers (where every number in the list occurs twice except for one).
function findNonPaired(listOfNumbers) {
let nonPairedNumber = 0
listOfNumbers.forEach((n) => {
nonPairedNumber ^= n
})
return nonPairedNumber
}
const x = [1,5,4,3,9,2,3,1,4,5,9]
console.log(findNonPaired(x))
This solution looks very elegant, but I'm curious at to what the ^= operator is actually doing here?
a ^= b is the same as a = a ^ b where ^ is the bitwise XOR operator.
0 ^ 0 === 0
1 ^ 0 === 1
0 ^ 1 === 1
1 ^ 1 === 0
This is a neat algorithm. Let's trace one execution with the list [8, 12, 8] for example:
0 ^ 8 = 0000 ^ 1000 = 1000
1000 ^ 1100 = 0100
0100 ^ 1000 = 1100 = 12
The word "duplicate" isn't correct. This algorithm tests for parity. A simple but somewhat wrong definition is "when everything has a pair". pair...parity.
[2,2,2,3,3,5,5,5,5] will return 2 because everything else has a pair.
[3,4,5] will actually return 2 (011^100^101 -> 010) because that is the xor of all the unpaired items.
Like other answers say - it is a bitwise XOR.
About the algorythm - it is cool if you are sure that the duplicates are even count. When a number is XOR-ed with x and later again XOR-ed with x it will return to it's previuos value. If one number is seen 3 times in this chain, the 3-rd occurence will fool this algorythm.
Also if there is one more value that is single in the chain, like:
a, b, c, X, a, c, b, Y
the result will be (X ^ Y) and you can't be sure if you have one unique value or more.
This question already has answers here:
How to print all possible balanced parentheses for an expression?
(9 answers)
Closed 5 years ago.
Imagine I have four letters a,b,c and d. I want to determine what are the ways to validly parenthesize and multiply them. For instance (a.b).(c.d) can be a solution or (a.(b.c)).d another solution. The number of combinations is 5 for 4 letters. (Which is also equivalent to Catalan Number n-1 in that case catalan number 3 which is 5).
I have realized that these combinations can be written as full binary trees and each binary tree represents one combination :
abcd abcd
/ \ / \ .....
/ \ / \
a bcd ab cd
/ \ / \ /\
bc d a b c d
/ \
b c
Starting from the deepest leaf, algorithm can generate for instance for the first tree : 1 - (b.c) then 2 - (b.c).d then 3- a.((b.c).d).
I want to have a recursive or normal function which can generate all the possible trees and do the multiplications but not sure how I can achieve that. Any help and suggestion is greatly appreciated.
Here's a JavaScript adaptation of ninjagecko's Python code from How to print all possible balanced parentheses for an expression?
function associations(seq, kw){
var grouper = kw.grouper || ((a,b) => [a,b]),
lifter = kw.lifter || (x => [x]);
if (seq.length === 1){
return lifter(seq[0]);
} else {
var result = [];
for (let i=1; i<seq.length; i++){
// split sequence on index i
var left = seq.slice(0,i),
right = seq.slice(i);
// return cartesian product of left x right
for (let l of associations(left,kw))
for (let r of associations(right,kw))
result.push(grouper(l,r));
}
return result;
}
}
console.log(JSON.stringify(associations([1,2,3,4],{})));
For word games, it is often the frequency of letters in English vocabulary, regardless of word frequency, which is of more interest.
1. >E 11.1607% 56.88 M 3.0129% 15.36
2. A 8.4966% 43.31 H 3.0034% 15.31
3. R 7.5809% 38.64 G 2.4705% 12.59
4. I 7.5448% 38.45 B 2.0720% 10.56
5. O 7.1635% 36.51 F 1.8121% 9.24
6. T 6.9509% 35.43 Y 1.7779% 9.06
7. N 6.6544% 33.92 W 1.2899% 6.57
8. S 5.7351% 29.23 K 1.1016% 5.61
9. L 5.4893% 27.98 V 1.0074% 5.13
10. C 4.5388% 23.13 X 0.2902% 1.48
11. U 3.6308% 18.51 Z 0.2722% 1.39
12. D 3.3844% 17.25 J 0.1965% 1.00
13. P 3.1671% 16.14 Q 0.1962% (1) <-
The third column represents proportions, taking the least common letter (q) as equal to 1. The letter E is over 56 times more common than Q in forming individual English words.
How is it possible to build an algorithm is javascript such that if I generate say 100 letters, 11-12% of then i.e. 11-12 letters will be E and so on.
Here's an algorithm:
Split the range [0, 1) in intervals that each matches a letter and has a size proportional to its probability. Eg
0 - 0.116: E
0.116 - 0.201: A
…
Get a random number between 0 and 1
Pick the interval that contains this number
Get the associated letter