Python - 轻松实现"比较"将一个数组映射到另一个数组

时间:2017-06-14 12:20:20

标签: python arrays pandas numpy

我有一个数组a = [1, 2, 3, 4, 5, 6]b = [1, 3, 5],我想映射a,以便a中的每个元素都在b之间b中的元素将被映射到a的索引,该索引是a = 1 -> 0 because a <= first element of b a = 2 -> 1 because b[0] < 2 <= b[1] and b[1] = 3 a = 3 -> 1 a = 4 -> 2 because b[1] < 4 <= b[2] 所包含的上限。不是单词中的最佳解释,但这里是一个示例< / p>

f(a, b) = [0, 1, 1, 2, 2, 2]

所以我想要的最终产品是 import arpa import ifaddrs class func getBothIPAddresses() -> [AnyHashable: Any] { let WIFI_IF: String = "en0" let KNOWN_WIRED_IFS: [Any] = ["en2", "en3", "en4"] let KNOWN_CELL_IFS: [Any] = ["pdp_ip0", "pdp_ip1", "pdp_ip2", "pdp_ip3"] let UNKNOWN_IP_ADDRESS: String = "" var addresses: [AnyHashable: Any] = ["wireless": UNKNOWN_IP_ADDRESS, "wired": UNKNOWN_IP_ADDRESS, "cell": UNKNOWN_IP_ADDRESS] var interfaces: ifaddrs? = nil var temp_addr: ifaddrs? = nil var success: Int = 0 // retrieve the current interfaces - returns 0 on success success = getifaddrs(interfaces) if success == 0 { // Loop through linked list of interfaces temp_addr = interfaces while temp_addr != nil { if temp_addr?.ifa_addr == nil { continue } if temp_addr?.ifa_addr?.sa_family == AF_INET { // Check if interface is en0 which is the wifi connection on the iPhone if (String(utf8String: temp_addr?.ifa_name) == WIFI_IF) { // Get NSString from C String addresses["wireless"] = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr)) } // Check if interface is a wired connection if KNOWN_WIRED_IFS.contains(String(utf8String: temp_addr?.ifa_name)) { addresses["wired"] = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr)) } // Check if interface is a cellular connection if KNOWN_CELL_IFS.contains(String(utf8String: temp_addr?.ifa_name)) { addresses["cell"] = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr)) } } temp_addr = temp_addr?.ifa_next } } // Free memory freeifaddrs(interfaces) return addresses }

我知道我可以循环并解决它,但我想知道在pandas / numpy中是否有一种聪明,快速(矢量化)的方法

2 个答案:

答案 0 :(得分:7)

使用python的bisect模块:

from bisect import bisect_left

a = [1, 2, 3, 4, 5, 6]
b = [1, 3, 5]

def f(_a, _b):
  return [bisect_left(_b, i) for i in _a]

print(f(a, b))
  

bisect - 数组平分算法

     

此模块支持按排序顺序维护列表,而无需在每次插入后对列表进行排序。对于具有昂贵比较操作的长项目列表,这可以是对更常见方法的改进。该模块称为bisect,因为它使用基本的二分算法来完成其工作。源代码作为算法的工作示例可能是最有用的(边界条件已经正确!)。

     

提供以下功能:

     

bisect.bisect_left(a, x, lo=0, hi=len(a))

     

a 中找到 x 的插入点,以维护排序顺序。参数 lo hi 可用于指定应考虑的列表的子集;默认情况下,使用整个列表。如果 x 已存在于 a 中,则插入点将位于任何现有条目之前(左侧)。   假设 a 已经排序,返回值适合用作list.insert()的第一个参数。

     

返回的插入点 i 将数组 a 分成两半,左侧为all(val < x for val in a[lo:i]),右侧为all(val >= x for val in a[i:hi])

参考: https://docs.python.org/3/library/bisect.html

答案 1 :(得分:2)

bisect更快:解决方案假定列表已排序

a = [1, 2, 3, 4, 5, 6]
b = [1, 3, 5]

inds=[min(bisect_left(b,x),len(b)-1) for x in a]

返回

[0, 1, 1, 2, 2, 2]