where
+ drop_duplicates
df['key'] = df['t_num'].where(df['o_st'].eq('P'), df['r_num'])
df.drop_duplicates(subset=['A_key', 'key']).drop('key', 1)
A_key t_num r_num o_st
292 A1 16 TS Q
173 A5 15 TT Q
955 A7 19 TQ Q
804 A7 17 TR Q
668 A1 28 None P
788 A4 88 None P
693 A7 17 TS Q
781 A1 22 None P
<час> У вас есть два отдельных подмножества, которые вы хотите проверить на уникальность в зависимости от значения третьего колонка. Вместо того, чтобы дважды вызывать drop_duplicates
, я создаю маску, которая содержит правильное значение подмножества, прежде чем вызывать drop_duplicates
один раз.
Это немного глупо, но я заставил его работать (при условии, что я понимаю, что вы хотите).
Сначала я создал класс модели представления:
class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
this.data.Add(1, "One");
this.data.Add(2, "Two");
this.data.Add(3, "Three");
}
Dictionary<int, string> data = new Dictionary<int, string>();
public IDictionary<int, string> Data
{
get { return this.data; }
}
private KeyValuePair<int, string>? selectedKey = null;
public KeyValuePair<int, string>? SelectedKey
{
get { return this.selectedKey; }
set
{
this.selectedKey = value;
this.OnPropertyChanged("SelectedKey");
this.OnPropertyChanged("SelectedValue");
}
}
public string SelectedValue
{
get
{
if(null == this.SelectedKey)
{
return string.Empty;
}
return this.data[this.SelectedKey.Value.Key];
}
set
{
this.data[this.SelectedKey.Value.Key] = value;
this.OnPropertyChanged("SelectedValue");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
var eh = this.PropertyChanged;
if(null != eh)
{
eh(this, new PropertyChangedEventArgs(propName));
}
}
}
А затем в XAML:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox x:Name="ItemsListBox" Grid.Row="0"
ItemsSource="{Binding Path=Data}"
DisplayMemberPath="Key"
SelectedItem="{Binding Path=SelectedKey}">
</ListBox>
<TextBox Grid.Row="1"
Text="{Binding Path=SelectedValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
Значение свойства Data
привязано к ItemsSource
из ListBox
. Как вы указали в вопросе, это приводит к использованию экземпляров KeyValuePair<int, string>
в качестве данных за ListBox
. Я установил DisplayMemberPath
на Key
, чтобы значение клавиши использовалось в качестве отображаемого значения для каждого элемента в ListBox
.
Как вы обнаружили, вы не можете просто использовать Value
из KeyValuePair
в качестве данных для TextBox
, так как это только для чтения. Вместо этого TextBox
привязывается к свойству в модели представления, которое может получить и установить значение для выбранного в данный момент ключа (которое обновляется путем привязки свойства SelectedItem
в ListBox
к другому свойству в модели представления ). Мне пришлось сделать это свойство обнуляемым (поскольку KeyValuePair
является структурой), чтобы код мог обнаруживать, когда выбора нет.
В моем тестовом приложении это, кажется, привело к правке TextBox
, распространяющейся на Dictionary
в модели представления.
Вместо
Dictionary<string, int>
вы можете иметь
Dictionary<string, IntWrapperClass>?
В IntWrapperClass реализован INotifyPropertyCHanged. Затем вы можете иметь двустороннюю привязку Listview / Listbox к элементам в словаре.
A good start is to decide what do you and do you not want to accept as an email address?
99% of of email addresses look like this: bob.smith@foo.com or fred@bla.edu
However, it's technically legal to have an email address like this: f!#$%&'*+-/=?^_
{|}~"ha!"@com
There are probably only a handful of valid emails in the world for top-level domains, and almost nobody uses most of those other characters (especially quotes and backticks), so you might want to assume that these are all invalid things to do. But you should do so as a conscious decision.
Beyond that, do what Paul says and try to match the input to a regular expression like this: ^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}$
That one will match pretty much everybody's email address.
Пользовательский класс
public class MyCustomClass
{
public string Key { get; set; }
public int Value { get; set; }
}
Set ItemsSource
ObservableCollection<MyCustomClass> dict = new ObservableCollection<MyCustomClass>();
dict.Add(new MyCustomClass{Key = "test", Value = 1});
dict.Add(new MyCustomClass{ Key = "test2", Value = 2 });
listView.ItemsSource = dict;
XAML
<Window.Resources>
<DataTemplate x:Key="ValueTemplate">
<TextBox Text="{Binding Value}" />
</DataTemplate>
</Window.Resources>
<ListView Name="listView">
<ListView.View>
<GridView>
<GridViewColumn CellTemplate="{StaticResource ValueTemplate}"/>
</GridView>
</ListView.View>
</ListView>