我有以下4个列表:
A= [1,2,3],
B=[4,5,6],
C=[7,8,9],
D=[10,11,12]
我想获取另一个列表列表,其第一个元素获取每个列表的第一个元素,第二个元素获取每个列表的第二个元素,等等。例如:
[1,2,3], [4,5,6], [7,8,9], [10,11,12]
成为
[[1,4,7,10], [2,5,8,11],[3,6,9,12]].
我尝试使用
findall([X,Y,Z,T],(member(X,A),member(Y,B),member(Z,C),member(T,D)),ModifiedList).
但这没用。
如何在Prolog中做到这一点?
答案 0 :(得分:3)
解决方案是:
% auxiliary predicate to group the first elements of
% all input lists and return the tails of the lists
group_first([], [], []).
group_first([[X| Xs]| Lists], [X| Tail], [Xs| Tails]) :-
group_first(Lists, Tail, Tails).
% main predicate; we separate the first list from the other
% lists to take advantage of first-argument indexing
group([], []).
group([List| Lists], Groups) :-
group(List, Lists, Groups).
group([], _, []).
group([X| Xs], Lists, [Group| Groups]) :-
group_first([[X| Xs]| Lists], Group, Tails),
group(Tails, Groups).
通话示例:
| ?- group([[1,2,3],[a,b,c],['A','B','C']], R).
R = [[1,a,'A'],[2,b,'B'],[3,c,'C']]
yes
为帮助您了解解决方案:
| ?- group_first([[1,2,3],[a,b,c],['A','B','C']], Group, Tails).
Group = [1,a,'A']
Tails = [[2,3],[b,c],['B','C']]
yes
答案 1 :(得分:1)
您所描述的只是转置/ 2:
?- [library(clpfd)].
true.
?- transpose([[1,2],[3,4],[5,6]],T).
T = [[1, 3, 5], [2, 4, 6]].
请注意,Paulo的回答很有趣:这是他在图书馆(yall)中的group_first / 3
group_first(A,B,C) :- maplist([U,V,Z]>>(U=[X|Xs],V=X,Z=Xs),A,B,C).
或更有效
group_first(A,B,C) :- maplist([[X|Xs],X,Xs]>>true,A,B,C).
group / 2的速度比clpfd:transpose:
快得多?- N=100,length(M,N),maplist({N}/[R]>>length(R,N),M),time(group(M,T)).
% 20,402 inferences, 0.009 CPU in 0.009 seconds (100% CPU, 2165467 Lips)
?- N=100,length(M,N),maplist({N}/[R]>>length(R,N),M),time(transpose(M,T)).
% 30,708 inferences, 0.010 CPU in 0.010 seconds (100% CPU, 3192701 Lips)
在原始Paulo答案中仍然更好(group_first未内联):
?- N=100,length(M,N),maplist({N}/[R]>>length(R,N),M),time(group(M,T)).
% 10,302 inferences, 0.004 CPU in 0.004 seconds (100% CPU, 2513070 Lips)
并且(几乎)是可逆的:
?- group(T,[[1,2]]).
T = [[1], [2|_5420]].
似乎是对库(clpfd)进行拉取请求的理想选择...
答案 2 :(得分:0)
这是另一种方法:
?- dim(77,66,L), time((between(1,100,_), transpose(L,_), fail; true)).
% 1,577,201 inferences, 0.103 CPU in 0.104 seconds (99% CPU, 15244107 Lips)
?- dim(77,66,L), time((between(1,100,_), nifty(L,_), fail; true)).
% 521,601 inferences, 0.062 CPU in 0.063 seconds (99% CPU, 8368647 Lips)
?- dim(77,66,L), time((between(1,100,_), group(L,_), fail; true)).
% 528,300 inferences, 0.048 CPU in 0.049 seconds (98% CPU, 11105739 Lips)
它在速度上排名第二:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)
?- nifty([[1,2,3],[4,5,6]],X).
X = [[1, 4], [2, 5], [3, 6]].
?- nifty([[1,4],[2,5],[3,6]],X).
X = [[1, 2, 3], [4, 5, 6]] ;
false.
?- nifty(X,[[1,2,3],[4,5,6]]).
X = [[1, 4], [2, 5], [3, 6]] ;
false.
?- nifty(X,[[1,4],[2,5],[3,6]]).
X = [[1, 2, 3], [4, 5, 6]].
但是它是完全双向的,即使在SWI-Prolog中也是如此:
Jekejeke Prolog 3, Runtime Library 1.3.8 (23 May 2019)
?- nifty([[1,2,3],[4,5,6]], X).
X = [[1,4],[2,5],[3,6]]
?- nifty([[1,4],[2,5],[3,6]], X).
X = [[1,2,3],[4,5,6]]
?- nifty(X, [[1,2,3],[4,5,6]]).
X = [[1,4],[2,5],[3,6]]
?- nifty(X, [[1,4],[2,5],[3,6]]).
X = [[1,2,3],[4,5,6]]
如果Prolog系统像Jekejeke Prolog中那样提供及时的多参数索引,那么即使事不宜迟,它也不会留下任何选择点:
from PyQt5 import QtCore, QtGui, QtWidgets
class HeaderProxyStyle(QtWidgets.QProxyStyle):
def drawControl(self, element, option, painter, widget=None):
if element == QtWidgets.QStyle.CE_Header:
option.text = ""
super(HeaderProxyStyle, self).drawControl(
element, option, painter, widget
)
class LabelHeaderView(QtWidgets.QHeaderView):
def __init__(self, parent):
super(LabelHeaderView, self).__init__(QtCore.Qt.Horizontal, parent)
self.m_labels = []
self.sectionResized.connect(self.adjustPositions)
self.sectionCountChanged.connect(self.onSectionCountChanged)
self.parent().horizontalScrollBar().valueChanged.connect(
self.adjustPositions
)
proxy_style = HeaderProxyStyle(self.style())
self.setStyle(proxy_style)
@QtCore.pyqtSlot()
def onSectionCountChanged(self):
while self.m_labels:
label = self.m_labels.pop()
label.deleteLater()
for i in range(self.count()):
label = QtWidgets.QLabel(self, alignment=QtCore.Qt.AlignCenter)
self.m_labels.append(label)
self.update_data()
self.adjustPositions()
def setModel(self, model):
super(LabelHeaderView, self).setModel(model)
if self.model() is not None:
self.model().headerDataChanged.connect(self.update_data)
def update_data(self):
option = QtWidgets.QStyleOptionHeader()
self.initStyleOption(option)
for i, label in enumerate(self.m_labels):
text = self.model().headerData(
i, self.orientation(), QtCore.Qt.DisplayRole
)
label.setText(str(text))
pal = label.palette()
bc = self.model().headerData(
i, self.orientation(), QtCore.Qt.BackgroundRole
)
if bc is None:
bc = option.palette.brush(QtGui.QPalette.Window)
pal.setBrush(QtGui.QPalette.Window, bc)
fc = self.model().headerData(
i, self.orientation(), QtCore.Qt.ForegroundRole
)
if fc is None:
fc = option.palette.brush(QtGui.QPalette.ButtonText)
pal.setBrush(QtGui.QPalette.ButtonText, fc)
label.setPalette(pal)
textAlignment = self.model().headerData(
i, self.orientation(), QtCore.Qt.TextAlignmentRole
)
if textAlignment is None:
textAlignment = self.defaultAlignment()
label.setAlignment(textAlignment)
def updateGeometries(self):
super(LabelHeaderView, self).updateGeometries()
self.adjustPositions()
@QtCore.pyqtSlot()
def adjustPositions(self):
for index, label in enumerate(self.m_labels):
geom = QtCore.QRect(
self.sectionViewportPosition(index),
0,
self.sectionSize(index),
self.height(),
)
geom.adjust(2, 0, -2, 0)
label.setGeometry(geom)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QTableWidget(10, 10)
header = LabelHeaderView(w)
w.setHorizontalHeader(header)
header_labels = []
for i in range(w.columnCount()):
header_label = "<sub>%s</sub><b>Header</b><sup>%s</sup>" % (i, i)
header_labels.append(header_label)
w.setHorizontalHeaderLabels(header_labels)
w.resize(320, 240)
w.show()
sys.exit(app.exec_())