Roughly speaking I am looking for a more elegant alternative for this snippet:
# my_list = range(6) # example list
my_list = ["this", "is", "an", "example", "list"]
max = len(my_list)
for i, elem in enumerate(my_list, start=1):
if i < max:
print elem, my_list[i]
which produces:
this is
is an
an example
example list
Is there some builtin for that?
Edit: I should have said, that I took range(6) as a representant for any iterable to avoid confusion. The goal was to iterate over an iterable pairwise pictured by the result above.
I usually do this:
# x = range(6)
x = ["this", "is", "an", "example", "list"]
for prv, nxt in zip(x, x[1:]):
print prv, nxt
There is no builtin, but the docs for the itertools module contains definition of the pairwise function that does the same.
Related
I have two lists, let's say:
def list1 = ["ABC", "DEF", "GHI", "JKL"]
def list2 = ["ABC", "DEF", "JKL", "GHI"]
I want to compare these two lists and make sure that the values they have are the same, despite the order in which they appear.
I've tried this but it doesn't seem to work:
assert new HashSet( Arrays.asList(list1)).equals(new HashSet( Arrays.asList(list2)))
Could anyone point me in the right direction?
Much appreciated.
If you want to stay with Lists and not use Sets, you can compare sorted lists:
def list1 = ["ABC", "DEF", "GHI", "JKL"]
def list2 = ["ABC", "DEF", "JKL", "GHI"]
assert list1 != list2
assert list1.sort() == list2.sort()
The suggested Set-based comparison might be dangerous, it the lists contain different numbers of duplicates:
def list1 = ["ABC"]
def list2 = ["ABC", "ABC", "ABC"]
assert list1.sort() != list2.sort()
assert list1 as Set == list2 as Set // GOTCHA!
Your comparison is not working because you're comparing sets of lists.
new HashSet(Arrays.asList()) creates a HashSet<List<String>> (roughly), and when Set equality is being checked, the element-wise comparison calls the usual List.equals, which doesn't work because order matters in lists.
Your lists should make flat elements in target sets for it to work based on Set comparison logic (such that you compare instances of HashSet<String> instead of HashSet<List<String>>). Your code should be
new HashSet(list1).equals(new HashSet(list2))
I'm trying to compare elements of 2 lists of lists in python. I want to create a new list (ph) which has a 1 if elements of lists from the 1st list of lists are in the elements of the 2nd list of lists.
However, this seems to compare the whole list and not individual elements. The code is below. Many thanks for the help! :)
import numpy as np
import pandas as pd
abc = [[1,800000,3],[4,5,6],[100000,7,8]]
l = [[
[i for i in range(0, 100000)],
[i for i in range(200000,300000)],
[i for i in range(400000,500000)],
[i for i in range(600000,700000)],
[i for i in range(800000,900000)],
[i for i in range(1000000,1100000)]
]]
ph = []
for i in abc:
for j in l:
if l[0] == abc[0]:
ph.append(1)
else:
ph.append(0)
print(ph)
The goal of your problem is somewhat unclear to me. Correct me if I'm wrong but what you want is: for each sublist of abc, get a boolean describing if all its elements are anywhere in l. Is that it ?
If it is indeed the case, here's my answer.
First of all, your second list is not a list of lists but a list of lists of lists. Hence, I removed a nested list in my code.
abc = [[1,800000,3],[4,5,6],[100000,7,8]]
L = [
[i for i in range(0, 100000)],
[i for i in range(200000,300000)],
[i for i in range(400000,500000)],
[i for i in range(600000,700000)],
[i for i in range(800000,900000)],
[i for i in range(1000000,1100000)]
]
flattened_L = sum(L, [])
print(
list(map(lambda sublist: all(x in flattened_L for x in sublist), abc))
)
# returns [True, True, False]
My code first flattens L so that is becomes easy to check whether any element is in it or not. Then, for each sublist in abc, it checks if all elements are in this flattened list.
Note: my code returns a list of boolean. If you absolutely need integers value (0 and 1), which you shouldn't, you can wrap int around all.
I have a list of strings stringlist = ["elementOne" , "elementTwo" , "elementThree"] and I would like to search for elements that contain the "Two" string and delete that from the list so my list will become stringlist = ["elementOne" , "elementThree"]
I managed to print them but don't really know how to delete completely from the list using del because i don't know the index or by using stringlist.remove("elementTwo") because I don't know the exact string of the element containing "Two"
My code so far:
for x in stringlist:
if "Two" in x:
print(x)
Normally when we perform list comprehension, we build a new list and assign it the same name as the old list. Though this will get the desired result, but this will not remove the old list in place.
To make sure the reference remains the same, you must use this:
>>> stringlist[:] = [x for x in stringlist if "Two" not in x]
>>> stringlist
['elementOne', 'elementThree']
Advantages:
Since it is assigning to a list slice, it will replace the contents with the same Python list object, so the reference remains the same, thereby preventing some bugs if it is being referenced elsewhere.
If you do this below, you will lose the reference to the original list.
>>> stringlist = [x for x in stringlist if "Two" not in x]
>>> stringlist
['elementOne', 'elementThree']
So to preserve the reference, you build the list object and assign it the list slice.
To understand the subtle difference:
Let us take a list a1 containing some elements and assign list a2 equal to a1.
>>> a1 = [1,2,3,4]
>>> a2 = a1
Approach-1:
>>> a1 = [x for x in a1 if x<2]
>>> a1
[1]
>>> a2
[1,2,3,4]
Approach-2:
>>> a1[:] = [x for x in a1 if x<2]
>>> a1
[1]
>>> a2
[1]
Approach-2 actually replaces the contents of the original a1 list whereas Approach-1 does not.
You can use enumerate to get the index when you iterate over your list (but Note that this is not a pythonic and safe way to modify your list while iterating over it):
>>> for i,x in enumerate(stringlist):
... if "Two" in x:
... print(x)
... del stringlist[i]
...
elementTwo
>>> stringlist
['elementOne', 'elementThree']
But as a more elegant and pythonic way you can use a list comprehension to preserve the elements that doesn't contains Two :
>>> stringlist = [i for i in stringlist if not "Two" in i]
>>> stringlist
['elementOne', 'elementThree']
Doing this will help you
for i,x in enumerate(stringlist):
if "Two" in x:
del stringlist[i]
or
newList = []
for x in stringlist:
if "Two" in x:
continue
else
newList.append(x)
Using regex,
import re
txt = ["SpainTwo", "StringOne"]
for i in txt:
x = re.search(r"Two", i)
if x:
temp_list = temp_list + [x.string] if "temp_list" in locals() else [x.string]
print(temp_list)
gives
['SpainTwo']
print(list(filter(lambda x: "Two" not in x, ["elementOne" , "elementTwo" , "elementThree", "elementTwo"])))
Using lambda, if you are only looking to print.
if you want to check for multiple string and delete if detected from list of string use following method
List_of_string = [ "easyapplyone", "appliedtwotime", "approachednone", "seenthreetime", "oneseen", "twoapproached"]
q = ["one","three"]
List_of_string[:] = [x for x in List_of_string if any(xs not in x for xs in q)]
print(List_of_string)
output:[ "approachednone", "seenthreetime"]
Well this was pretty simple - sorry for all the trouble
for x in stringlist:
if "Two" in x:
stringlist.remove(x)
I have a list in Scala that I'm trying to partition into multiple lists based on a predicate that involves multiple elements of the list. For example, if I have
a: List[String] = List("a", "ab", "b", "abc", "c")
I want to get b: List[List[String]] which is a List of List[String] such that the sum of the lengths of the inner List[String] == 3. i.e List(List("a", "b", "c"), List("abc"), List("ab", "a"), ...)
[Edit] Needs to take a reasonable time for lists of length 50 or less.
It is not possible to build an efficient algorithm that is cheaper than O(2^n * O(p)) for any arbitrary predicate, p. This is because every subset must be evaluated. You will never achieve something that works for n == 50.
Build all possible sublists and filter:
def filter[A](list: List[A])(predicate: (List[A] => Boolean)): List[List[A]] = {
(for {i <- 1 to list.length
subList <- list.combinations(i)
if predicate(subList)
} yield subList).toList
}
val a = List("a", "ab", "b", "abc", "c")
val result = filter(a)(_.foldLeft(0)(_ + _.length) == 3)
I think Sergey is on a good track here, but we can optimize his code a little bit. First of all, we can notice that if the sum of string lengths is N then for sure we don't need to check combinations composed of more than N strings, as the shortest string is at least one character long. And, additionally, we can get away without for synctatic sugar and use the sum method instead of a much more generic (and thus, probably, not so quick) foldLeft.
For clarity's sake, let's first define a small helper function which will compute the sum of strings lengths:
def sumOfStr(list: List[String]) = list.map(_.length).sum
And now the main method:
def split(list: List[String], sum: Int) =
(1 to sum).map(list.combinations(_).filter(sumOfStr(_) == sum)).flatten.toList
EDIT: With our powers combined, we give you a still very inefficient, but hey-that's-the-best-we-can-do-in-reasonable-time version:
def sumOfStr(lst: List[String]) = {
var sum = 0
lst.foreach{ sum += _.length }
sum
}
def split(lst: List[String], sum: Int) =
(1 to sum).par
.map(lst.combinations(_).filter(sumOfStr(_) == sum))
.flatten.toList
I'm new to Python and trying to use re.sub or other approach to find individual items in a list and replace with multiple items. For example:
import re
list = ['abc', 'def']
tolist = []
for item in list:
a = re.sub(r'^(.)(.)(.)$', '\\1\\2', '\\2\\3', item)
tolist.append(a)
print tolist # want: ['ab', 'bc', 'de', 'ef']
The '\1\2', '\2\3' part clearly doesn't work, just there to lamely illustrate the idea.
You could pair characters without regexes:
lst = ['abc', 'def']
result = [a+b for chars in lst for a, b in zip(chars, chars[1:])]
print(result)
# -> ['ab', 'bc', 'de', 'ef']
Here's a rather generic approach where you have a list of tuples for all the substitutions you want to do with each item:
In [1]: import re
In [2]: subs = [(r'^(.)(.)(.)$', r'\1\2'), (r'^(.)(.)(.)$', r'\2\3')]
In [3]: inlist = ['abc', 'def']
In [4]: [re.sub(*sub, string=s) for s in inlist for sub in subs]
Out[4]: ['ab', 'bc', 'de', 'ef']
The second element in each tuple can also be a function, because re.sub allows it. I renamed your initial list because list is a built-in type name and shouldn't be used for variables.
>>> res = []
>>> m = re.compile('(..)')
>>> for items in list:
... for p in range(0,len(items)):
... r = m.search(items[p:])
... if r != None:
... res.append(r.group())
make a regexp that matches two characters and groups them
first for loop, iterate the list
second for loop, character indexes in each list item
search for the character pairs starting at further on offsets
store anything that's found