Если вы пришли сюда, чтобы выбрать строки из фрейма данных, включив те, чье значение столбца НЕ является ни одним из списка значений, вот как перевернуть ответ unutbu для списка значений выше:
df.loc[~df['column_name'].isin(some_values)]
(Чтобы не включать одно значение, конечно, вы просто используете обычный оператор не равно, !=
.)
Пример:
import pandas as pd
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
'B': 'one one two three two two one three'.split()})
print(df)
дает нам
A B
0 foo one
1 bar one
2 foo two
3 bar three
4 foo two
5 bar two
6 foo one
7 foo three
Подмножество только для тех строк, которые ARE NOT one
или three
в столбце B
:
df.loc[~df['B'].isin(['one', 'three'])]
дает
A B
2 foo two
4 foo two
5 bar two
Ниже приведен итеративный подход (в отличие от рекурсивного решения), который вы можете использовать для достижения своего результата. По сути, начните с поиска корневого элемента, а затем переберите исходный массив, ища элементы, у которых текущий элемент является родительским.
Чтобы добиться замены родительской электронной почты идентификатором, просто сохраните карту родительских имен с идентификаторами:
var data = [{
"id": 1,
"email": "a@b.com", // unique
"parent": "c@b.com" // is nullable
}, {
"id": 2,
"email": "b@b.com",
"parent": null
}, {
"id": 3,
"email": "c@b.com",
"parent": "b@b.com"
}, {
"id": 4,
"email": "d@b.com",
"parent": "a@b.com"
}]
//Map email addresses to IDs
var map = data.reduce((accum, el) => {
accum[el.email] = {
id: el.id
}
return accum;
}, {});
var [root] = data.filter(el => !el.parent);
var users = [root];
var cur;
var children;
while (users.length < data.length) {
cur = users[users.length - 1];
//Find elments that have cur as parent
children = data.filter(el => el.parent === cur.email);
children.forEach(el => {
users.push({
id: el.id,
email: el.email,
parent: map[el.parent].id
});
});
}
console.log(users)
Я подойду к этому, сначала сгенерировав новый вход с заменой parent email
на parent id
и новым свойством уровня узла, связанным с деревом, которому они принадлежат. Тогда мы можем отсортировать узлы по этому свойству level
, а по равному level
мы отсортируем по id
.
const input = [
{"id": 1, "email": "a@b.com", "parent": "c@b.com"},
{"id": 2, "email": "b@b.com", "parent": null},
{"id": 3, "email": "c@b.com", "parent": "b@b.com"},
{"id": 4, "email": "d@b.com", "parent": "a@b.com"},
{"id": 5, "email": "x@b.com", "parent": "b@b.com"},
{"id": 6, "email": "z@b.com", "parent": "x@b.com"},
{"id": 7, "email": "y@b.com", "parent": null},
{"id": 8, "email": "m@b.com", "parent": "y@b.com"}
];
const findParent = (mail) => input.find(x => x.email === mail);
const getLevel = (mail, lvl) =>
{
return mail ? getLevel(findParent(mail).parent, lvl + 1) : lvl;
}
let newInput = input.map(({id, email, parent}) =>
{
return {
id: id,
email: email,
parent: findParent(parent) ? findParent(parent).id : null,
lvl: getLevel(parent, 0)
};
});
let sortedInput = newInput.sort((a, b) =>
{
return (a.lvl - b.lvl) ? a.lvl - b.lvl : a.id - b.id;
});
console.log(sortedInput);