Project

General

Profile

patch.diff

built-in Hash#slice, Hash#slice!, Hash#except, and Hash#except! - Glass_saga (Masaki Matsushita), 07/26/2013 10:58 PM

View differences:

hash.c
1085 1085
    return rb_hash_delete_if(rb_obj_dup(hash));
1086 1086
}
1087 1087

  
1088
struct slice_i_arg {
1089
    int argc;
1090
    VALUE *argv;
1091
};
1092

  
1093
static int
1094
slice_i(VALUE key, VALUE value, VALUE arg)
1095
{
1096
    int i;
1097
    struct slice_i_arg *p = (struct slice_i_arg *)arg;
1098
    VALUE key_to_slice;
1099

  
1100
    for (i = 0; i < p->argc; i++) {
1101
	key_to_slice = p->argv[i];
1102
	if (rb_equal(key, key_to_slice))
1103
	    return ST_CONTINUE;
1104
    }
1105

  
1106
    return ST_DELETE;
1107
}
1108

  
1109
static VALUE
1110
rb_hash_slice_bang(int argc, VALUE *argv, VALUE hash)
1111
{
1112
    st_index_t n;
1113

  
1114
    rb_hash_modify(hash);
1115
    n = RHASH_SIZE(hash);
1116
    if (!n) return Qnil;
1117
    if (argc) {
1118
	struct slice_i_arg arg;
1119
	arg.argc = argc;
1120
	arg.argv = argv;
1121
	rb_hash_foreach(hash, slice_i, (VALUE)&arg);
1122
    }
1123
    else {
1124
	rb_hash_clear(hash);
1125
    }
1126

  
1127
    if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
1128
    return hash;
1129
}
1130

  
1131
static VALUE
1132
rb_hash_slice(int argc, VALUE *argv, VALUE hash)
1133
{
1134
    int i;
1135
    VALUE key, value, result = rb_hash_new();
1136

  
1137
    if (!argc || RHASH_EMPTY_P(hash)) return result;
1138

  
1139
    for (i = 0; i < argc; i++) {
1140
	key = argv[i];
1141
	value = rb_hash_lookup2(hash, key, Qundef);
1142
	if (value != Qundef)
1143
	    rb_hash_aset(result, key, value);
1144
    }
1145

  
1146
    return result;
1147
}
1148

  
1149
struct except_i_arg {
1150
    int argc;
1151
    VALUE *argv;
1152
};
1153

  
1154
static int
1155
except_i(VALUE key, VALUE value, VALUE arg)
1156
{
1157
    int i;
1158
    struct except_i_arg *p = (struct except_i_arg *)arg;
1159
    VALUE key_to_except;
1160

  
1161
    for (i = 0; i < p->argc; i++) {
1162
	key_to_except = p->argv[i];
1163
	if (rb_equal(key, key_to_except))
1164
	    return ST_DELETE;
1165
    }
1166

  
1167
    return ST_CONTINUE;
1168
}
1169

  
1170
static VALUE
1171
rb_hash_except_bang(int argc, VALUE *argv, VALUE hash)
1172
{
1173
    st_index_t n;
1174
    struct except_i_arg arg;
1175

  
1176
    rb_hash_modify(hash);
1177
    n = RHASH_SIZE(hash);
1178
    if (!n || !argc) return Qnil;
1179
    arg.argc = argc;
1180
    arg.argv = argv;
1181
    rb_hash_foreach(hash, except_i, (VALUE)&arg);
1182

  
1183
    if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
1184
    return hash;
1185
}
1186

  
1187
static VALUE
1188
rb_hash_except(int argc, VALUE *argv, VALUE hash)
1189
{
1190
    VALUE result = rb_obj_dup(hash);
1191
    rb_hash_except_bang(argc, argv, result);
1192
    return result;
1193
}
1194

  
1088 1195
/*
1089 1196
 * call-seq:
1090 1197
 *   hsh.values_at(key, ...)   -> array
......
3597 3704
    rb_define_method(rb_cHash,"select!", rb_hash_select_bang, 0);
3598 3705
    rb_define_method(rb_cHash,"reject", rb_hash_reject, 0);
3599 3706
    rb_define_method(rb_cHash,"reject!", rb_hash_reject_bang, 0);
3707
    rb_define_method(rb_cHash,"slice", rb_hash_slice, -1);
3708
    rb_define_method(rb_cHash,"slice!", rb_hash_slice_bang, -1);
3709
    rb_define_method(rb_cHash,"except", rb_hash_except, -1);
3710
    rb_define_method(rb_cHash,"except!", rb_hash_except_bang, -1);
3600 3711
    rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
3601 3712
    rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
3602 3713
    rb_define_method(rb_cHash,"update", rb_hash_update, 1);
test/ruby/test_hash.rb
796 796
    assert_equal(nil, h.select!{true})
797 797
  end
798 798

  
799
  def test_slice
800
    h = {1=>2,3=>4,5=>6}
801
    assert_equal({1=>2, 3=>4}, h.slice(1, 3))
802
    assert_equal({}, h.slice)
803
  end
804

  
805
  def test_slice!
806
    h = {1=>2,3=>4,5=>6}
807
    assert_equal({1=>2, 3=>4}, h.slice!(1, 3))
808
    assert_equal({1=>2, 3=>4}, h)
809
    assert_equal(nil, h.slice!(1, 3))
810
    assert_equal({}, h.slice!(7))
811
    assert_equal(nil, h.slice!)
812
  end
813

  
814
  def test_except
815
    h = {1=>2,3=>4,5=>6}
816
    assert_equal({5=>6}, h.except(1, 3))
817
    assert_equal(h, h.except)
818
  end
819

  
820
  def test_except!
821
    h = {1=>2,3=>4,5=>6}
822
    assert_equal({5=>6}, h.except!(1, 3))
823
    assert_equal({5=>6}, h)
824
    assert_equal(nil, h.except!(1,3))
825
    assert_equal(nil, h.except!)
826
    assert_equal({5=>6}, h)
827
  end
828

  
799 829
  def test_clear2
800 830
    assert_equal({}, {1=>2,3=>4,5=>6}.clear)
801 831
    h = {1=>2,3=>4,5=>6}